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 Sake -version 0.2 -o packages -ExcludeVersion
|
||||
|
||||
IF "%SKIP_KRE_INSTALL%"=="1" goto run
|
||||
CALL packages\KoreBuild\build\kvm upgrade -runtime CLR -x86
|
||||
CALL packages\KoreBuild\build\kvm install default -runtime CoreCLR -x86
|
||||
IF "%SKIP_DOTNET_INSTALL%"=="1" goto run
|
||||
CALL packages\KoreBuild\build\dotnetsdk upgrade -runtime CLR -x86
|
||||
CALL packages\KoreBuild\build\dotnetsdk install default -runtime CoreCLR -x86
|
||||
|
||||
: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 %*
|
||||
|
|
|
|||
4
build.sh
4
build.sh
|
|
@ -28,11 +28,11 @@ if test ! -d packages/KoreBuild; then
|
|||
fi
|
||||
|
||||
if ! type k > /dev/null 2>&1; then
|
||||
source packages/KoreBuild/build/kvm.sh
|
||||
source packages/KoreBuild/build/dotnetsdk.sh
|
||||
fi
|
||||
|
||||
if ! type k > /dev/null 2>&1; then
|
||||
kvm upgrade
|
||||
dotnetsdk upgrade
|
||||
fi
|
||||
|
||||
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"
|
||||
|
|
|
|||
|
|
@ -81,17 +81,17 @@ namespace Microsoft.AspNet.Razor.Runtime
|
|||
/// <summary>
|
||||
/// Parameter {0} must not contain null tag names.
|
||||
/// </summary>
|
||||
internal static string TagNameAttribute_AdditionalTagsCannotContainNull
|
||||
internal static string HtmlElementNameAttribute_AdditionalTagsCannotContainNull
|
||||
{
|
||||
get { return GetString("TagNameAttribute_AdditionalTagsCannotContainNull"); }
|
||||
get { return GetString("HtmlElementNameAttribute_AdditionalTagsCannotContainNull"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parameter {0} must not contain null tag names.
|
||||
/// </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>
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@
|
|||
<data name="ScopeManager_EndCannotBeCalledWithoutACallToBegin" xml:space="preserve">
|
||||
<value>Must call '{2}.{1}' before calling '{2}.{0}'.</value>
|
||||
</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>
|
||||
</data>
|
||||
<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.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class TagNameAttribute : Attribute
|
||||
public sealed class HtmlElementNameAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="TagNameAttribute"/> class.
|
||||
/// Instantiates a new instance of the <see cref="HtmlElementNameAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <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 };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="TagNameAttribute"/> class.
|
||||
/// Instantiates a new instance of the <see cref="HtmlElementNameAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
public TagNameAttribute([NotNull] string tag, [NotNull] params string[] additionalTags)
|
||||
public HtmlElementNameAttribute([NotNull] string tag, [NotNull] params string[] additionalTags)
|
||||
{
|
||||
if (additionalTags.Contains(null))
|
||||
{
|
||||
throw new ArgumentNullException(
|
||||
nameof(additionalTags),
|
||||
Resources.FormatTagNameAttribute_AdditionalTagsCannotContainNull(nameof(additionalTags)));
|
||||
Resources.FormatHtmlElementNameAttribute_AdditionalTagsCannotContainNull(nameof(additionalTags)));
|
||||
};
|
||||
|
||||
var allTags = new List<string>(additionalTags);
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
// 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.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||
{
|
||||
|
|
@ -10,18 +12,42 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
/// </summary>
|
||||
public class TagHelperContext
|
||||
{
|
||||
private readonly Func<Task<string>> _getChildContentAsync;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="TagHelperContext"/>.
|
||||
/// </summary>
|
||||
/// <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;
|
||||
UniqueId = uniqueId;
|
||||
_getChildContentAsync = getChildContentAsync;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Every attribute associated with the current HTML element.
|
||||
/// </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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||
|
|
@ -15,6 +16,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
public static class TagHelperDescriptorFactory
|
||||
{
|
||||
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:
|
||||
// https://github.com/aspnet/Razor/issues/165
|
||||
|
|
@ -29,21 +38,19 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var tagNames = GetTagNames(type);
|
||||
var typeName = type.FullName;
|
||||
var attributeDescriptors = GetAttributeDescriptors(type);
|
||||
var contentBehavior = GetContentBehavior(type);
|
||||
var assemblyName = type.GetTypeInfo().Assembly.GetName().Name;
|
||||
|
||||
return tagNames.Select(tagName =>
|
||||
new TagHelperDescriptor(tagName,
|
||||
typeName,
|
||||
assemblyName,
|
||||
contentBehavior,
|
||||
attributeDescriptors));
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetTagNames(Type tagHelperType)
|
||||
{
|
||||
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 (!attributes.Any())
|
||||
|
|
@ -55,7 +62,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
name = name.Substring(0, name.Length - TagHelperNameEnding.Length);
|
||||
}
|
||||
|
||||
return new[] { name };
|
||||
return new[] { ToHtmlCase(name) };
|
||||
}
|
||||
|
||||
// Remove duplicate tag names.
|
||||
|
|
@ -75,21 +82,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var attributeNameAttribute = property.GetCustomAttribute<HtmlAttributeNameAttribute>(inherit: false);
|
||||
var attributeName = attributeNameAttribute != null ?
|
||||
attributeNameAttribute.Name :
|
||||
property.Name;
|
||||
ToHtmlCase(property.Name);
|
||||
|
||||
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)
|
||||
{
|
||||
return property.GetMethod != null &&
|
||||
|
|
@ -97,5 +94,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
property.SetMethod != null &&
|
||||
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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||
{
|
||||
|
|
@ -12,28 +14,73 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
public class TagHelperExecutionContext
|
||||
{
|
||||
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>
|
||||
/// Instantiates a new <see cref="TagHelperExecutionContext"/>.
|
||||
/// </summary>
|
||||
/// <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);
|
||||
HTMLAttributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
_tagHelpers = new List<ITagHelper>();
|
||||
TagName = tagName;
|
||||
UniqueId = uniqueId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if <see cref="GetChildContentAsync"/> has been called.
|
||||
/// </summary>
|
||||
public bool ChildContentRetrieved
|
||||
{
|
||||
get
|
||||
{
|
||||
return _childContent != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HTML attributes.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> HTMLAttributes { get; private set; }
|
||||
public IDictionary<string, string> HTMLAttributes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="ITagHelper"/> bound attributes and HTML attributes.
|
||||
/// </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>
|
||||
/// <see cref="ITagHelper"/>s that should be run.
|
||||
|
|
@ -49,7 +96,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
/// <summary>
|
||||
/// The HTML tag name in the Razor source.
|
||||
/// </summary>
|
||||
public string TagName { get; private set; }
|
||||
public string TagName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ITagHelper"/>s' output.
|
||||
|
|
@ -85,5 +132,34 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
{
|
||||
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
|
||||
{
|
||||
private string _content;
|
||||
private string _tagName;
|
||||
private bool _contentSet;
|
||||
|
||||
// Internal for testing
|
||||
internal TagHelperOutput(string tagName)
|
||||
|
|
@ -24,48 +24,39 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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>
|
||||
/// Instantiates a new instance of <see cref="TagHelperOutput"/>.
|
||||
/// </summary>
|
||||
/// <param name="tagName">The HTML element's tag name.</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,
|
||||
string content)
|
||||
public TagHelperOutput(string tagName, [NotNull] IDictionary<string, string> attributes)
|
||||
{
|
||||
TagName = tagName;
|
||||
Content = content;
|
||||
Attributes = new Dictionary<string, string>(attributes, StringComparer.OrdinalIgnoreCase);
|
||||
PreContent = string.Empty;
|
||||
_content = string.Empty;
|
||||
PostContent = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The HTML element's tag name.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
public string TagName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _tagName;
|
||||
}
|
||||
set
|
||||
{
|
||||
_tagName = value ?? string.Empty;
|
||||
}
|
||||
}
|
||||
public string TagName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HTML element's content.
|
||||
/// The HTML element's pre content.
|
||||
/// </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
|
||||
{
|
||||
get
|
||||
|
|
@ -74,7 +65,25 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
}
|
||||
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>
|
||||
/// The HTML element's attributes.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Attributes { get; private set; }
|
||||
public IDictionary<string, string> Attributes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates the <see cref="TagHelperOutput"/>'s start tag.
|
||||
|
|
@ -126,6 +135,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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>
|
||||
/// Generates the <see cref="TagHelperOutput"/>'s body.
|
||||
/// </summary>
|
||||
|
|
@ -141,6 +166,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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>
|
||||
/// Generates the <see cref="TagHelperOutput"/>'s end tag.
|
||||
/// </summary>
|
||||
|
|
@ -155,5 +196,20 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
|
||||
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.
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||
|
|
@ -14,33 +13,17 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
/// <summary>
|
||||
/// Calls the <see cref="ITagHelper.ProcessAsync"/> method on <see cref="ITagHelper"/>s.
|
||||
/// </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
|
||||
/// <paramref name="context"/>'s <see cref="ITagHelper"/>s.</returns>
|
||||
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelperExecutionContext context)
|
||||
/// <paramref name="executionContext"/>'s <see cref="ITagHelper"/>s.</returns>
|
||||
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelperExecutionContext executionContext)
|
||||
{
|
||||
return await RunAsyncCore(context, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls the <see cref="ITagHelper.ProcessAsync"/> method on <see cref="ITagHelper"/>s.
|
||||
/// </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);
|
||||
var tagHelperContext = new TagHelperContext(
|
||||
executionContext.AllAttributes,
|
||||
executionContext.UniqueId,
|
||||
executionContext.GetChildContentAsync);
|
||||
var tagHelperOutput = new TagHelperOutput(executionContext.TagName, executionContext.HTMLAttributes);
|
||||
|
||||
foreach (var tagHelper in executionContext.TagHelpers)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||
{
|
||||
|
|
@ -25,10 +27,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
/// Starts a <see cref="TagHelperExecutionContext"/> scope.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
IEnumerable<TypeInfo> libraryTypes;
|
||||
try
|
||||
{
|
||||
libraryTypes = GetLibraryDefinedTypes(assemblyName);
|
||||
libraryTypes = GetExportedTypes(assemblyName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -72,8 +72,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
return validTagHelpers.Select(type => type.AsType());
|
||||
}
|
||||
|
||||
// Internal for testing, don't want to be loading assemblies during a test.
|
||||
internal virtual IEnumerable<TypeInfo> GetLibraryDefinedTypes(AssemblyName assemblyName)
|
||||
/// <summary>
|
||||
/// 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
"aspnet50": { },
|
||||
"aspnetcore50": {
|
||||
"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.
|
||||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -12,9 +14,14 @@ namespace Microsoft.AspNet.Razor.Generator
|
|||
/// Instantiates a new instance of the <see cref="CodeBuilderContext"/> object.
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
ErrorSink = errorSink;
|
||||
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
||||
}
|
||||
|
||||
|
|
@ -23,9 +30,11 @@ namespace Microsoft.AspNet.Razor.Generator
|
|||
string className,
|
||||
string rootNamespace,
|
||||
string sourceFile,
|
||||
bool shouldGenerateLinePragmas)
|
||||
bool shouldGenerateLinePragmas,
|
||||
ParserErrorSink errorSink)
|
||||
: base(host, className, rootNamespace, sourceFile, shouldGenerateLinePragmas)
|
||||
{
|
||||
ErrorSink = errorSink;
|
||||
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
||||
}
|
||||
|
||||
|
|
@ -56,5 +65,10 @@ namespace Microsoft.AspNet.Razor.Generator
|
|||
/// <see cref="CodeGeneratorContext.SourceFile"/>.
|
||||
/// </summary>
|
||||
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
|
||||
writer.WriteLine();
|
||||
|
||||
new CSharpClassAttributeVisitor(writer, Context).Accept(Tree.Chunks);
|
||||
|
||||
using (BuildClassDeclaration(writer))
|
||||
{
|
||||
if (Host.DesignTimeMode)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||
|
|
@ -57,14 +58,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
{
|
||||
var tagHelperDescriptors = chunk.Descriptors;
|
||||
|
||||
// Find the first content behavior that doesn't have a content behavior of None.
|
||||
// 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);
|
||||
RenderBeginTagHelperScope(chunk.TagName, chunk.Children);
|
||||
|
||||
RenderTagHelpersCreation(chunk);
|
||||
|
||||
|
|
@ -77,42 +71,15 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
|
||||
RenderUnboundHTMLAttributes(unboundHTMLAttributes);
|
||||
|
||||
switch (contentBehavior)
|
||||
{
|
||||
case ContentBehavior.None:
|
||||
RenderRunTagHelpers(bufferedBody: false);
|
||||
RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
|
||||
RenderTagHelperBody(chunk.Children, bufferBody: false);
|
||||
RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
|
||||
break;
|
||||
case ContentBehavior.Append:
|
||||
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;
|
||||
}
|
||||
RenderRunTagHelpers();
|
||||
|
||||
RenderTagOutput(_tagHelperContext.OutputGenerateStartTagMethodName);
|
||||
RenderTagOutput(_tagHelperContext.OutputGeneratePreContentMethodName);
|
||||
|
||||
RenderTagHelperContent();
|
||||
|
||||
RenderTagOutput(_tagHelperContext.OutputGeneratePostContentMethodName);
|
||||
RenderTagOutput(_tagHelperContext.OutputGenerateEndTagMethodName);
|
||||
|
||||
RenderEndTagHelpersScope();
|
||||
}
|
||||
|
|
@ -122,11 +89,13 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
return "__" + descriptor.TypeName.Replace('.', '_');
|
||||
}
|
||||
|
||||
private void RenderBeginTagHelperScope(string tagName)
|
||||
private void RenderBeginTagHelperScope(string tagName, IList<Chunk> children)
|
||||
{
|
||||
// Scopes/execution contexts are a runtime feature.
|
||||
if (_designTimeMode)
|
||||
{
|
||||
// Render all of the tag helper children inline for IntelliSense.
|
||||
_bodyVisitor.Accept(children);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -135,10 +104,50 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
_writer.WriteStartAssignment(ExecutionContextVariableName)
|
||||
.WriteStartInstanceMethodInvocation(ScopeManagerVariableName,
|
||||
_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)
|
||||
.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();
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
var tagHelperDescriptors = chunk.Descriptors;
|
||||
|
|
@ -213,48 +222,67 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
tagHelperVariableName,
|
||||
attributeDescriptor.PropertyName);
|
||||
|
||||
_writer.WriteStartAssignment(valueAccessor);
|
||||
|
||||
// If we haven't recorded this attribute value before then we need to record its value.
|
||||
if (!attributeValueRecorded)
|
||||
{
|
||||
// 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
|
||||
// need the value.
|
||||
// We're saving the value accessor so we can retrieve it later if there are more tag
|
||||
// helpers that need the value.
|
||||
htmlAttributeValues.Add(attributeDescriptor.Name, valueAccessor);
|
||||
|
||||
if (bufferableAttribute)
|
||||
{
|
||||
// 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.
|
||||
_writer.WriteStartAssignment(valueAccessor);
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
_writer.WriteLine(";");
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Make complex types in non-bufferable attributes work in
|
||||
// https://github.com/aspnet/Razor/issues/129
|
||||
if (!isPlainTextValue)
|
||||
// Write out simple assignment for non-string property value. Try to keep the whole
|
||||
// statement together and the #line pragma correct to make debugging possible.
|
||||
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(";");
|
||||
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.
|
||||
if (_designTimeMode)
|
||||
{
|
||||
|
|
@ -262,20 +290,23 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
}
|
||||
|
||||
// We need to inform the context of the attribute value.
|
||||
_writer.WriteStartInstanceMethodInvocation(
|
||||
ExecutionContextVariableName,
|
||||
_tagHelperContext.ExecutionContextAddTagHelperAttributeMethodName);
|
||||
|
||||
_writer.WriteStringLiteral(attributeDescriptor.Name)
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueAccessor)
|
||||
.WriteEndMethodInvocation();
|
||||
_writer
|
||||
.WriteStartInstanceMethodInvocation(
|
||||
ExecutionContextVariableName,
|
||||
_tagHelperContext.ExecutionContextAddTagHelperAttributeMethodName)
|
||||
.WriteStringLiteral(attributeDescriptor.Name)
|
||||
.WriteParameterSeparator()
|
||||
.Write(valueAccessor)
|
||||
.WriteEndMethodInvocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The attribute value has already been recorded, lets retrieve it from the stored value accessors.
|
||||
_writer.Write(htmlAttributeValues[attributeDescriptor.Name])
|
||||
.WriteLine(";");
|
||||
// The attribute value has already been recorded, lets retrieve it from the stored value
|
||||
// accessors.
|
||||
_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.
|
||||
if (bufferBody)
|
||||
// Rendering output is a runtime feature.
|
||||
if (_designTimeMode)
|
||||
{
|
||||
// Render all of the tag helper children in a buffered writing scope.
|
||||
BuildBufferedWritingScope(children);
|
||||
return;
|
||||
}
|
||||
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.
|
||||
_bodyVisitor.Accept(children);
|
||||
RenderTagOutput(_tagHelperContext.OutputGenerateContentMethodName);
|
||||
}
|
||||
|
||||
_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();
|
||||
}
|
||||
|
||||
private void RenderRunTagHelpers(bool bufferedBody)
|
||||
private void RenderRunTagHelpers()
|
||||
{
|
||||
// No need to run anything in design time mode.
|
||||
if (_designTimeMode)
|
||||
|
|
@ -383,36 +470,38 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
.Write(" = ")
|
||||
.WriteStartInstanceMethodInvocation(RunnerVariableName,
|
||||
_tagHelperContext.RunnerRunAsyncMethodName);
|
||||
_writer.Write(ExecutionContextVariableName);
|
||||
|
||||
if (bufferedBody)
|
||||
{
|
||||
_writer.WriteParameterSeparator()
|
||||
.Write(StringValueBufferVariableName);
|
||||
}
|
||||
|
||||
_writer.WriteEndMethodInvocation(endLine: false)
|
||||
_writer.Write(ExecutionContextVariableName)
|
||||
.WriteEndMethodInvocation(endLine: false)
|
||||
.WriteLine(".Result;");
|
||||
}
|
||||
|
||||
private void RenderBufferedAttributeValue(TagHelperAttributeDescriptor attributeDescriptor)
|
||||
{
|
||||
// Pass complexValue: false because variable.ToString() replaces any original complexity in the expression.
|
||||
RenderAttributeValue(
|
||||
attributeDescriptor,
|
||||
valueRenderer: (writer) =>
|
||||
{
|
||||
RenderBufferedAttributeValueAccessor(writer);
|
||||
});
|
||||
},
|
||||
complexValue: false);
|
||||
}
|
||||
|
||||
private void RenderRawAttributeValue(string value, TagHelperAttributeDescriptor attributeDescriptor)
|
||||
private void RenderRawAttributeValue(
|
||||
Chunk attributeValueChunk,
|
||||
TagHelperAttributeDescriptor attributeDescriptor,
|
||||
bool isPlainTextValue)
|
||||
{
|
||||
RenderAttributeValue(
|
||||
attributeDescriptor,
|
||||
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)
|
||||
|
|
@ -422,7 +511,8 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
valueRenderer: (writer) =>
|
||||
{
|
||||
writer.WriteStringLiteral(value);
|
||||
});
|
||||
},
|
||||
complexValue: false);
|
||||
}
|
||||
|
||||
private void BuildBufferedWritingScope(Chunk htmlAttributeChunk)
|
||||
|
|
@ -473,9 +563,15 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
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,
|
||||
CSharpTagHelperCodeRenderer.StringValueBufferVariableName,
|
||||
value: null);
|
||||
Writer.WritePragma("warning restore 0414");
|
||||
|
||||
WritePrivateField(_tagHelperContext.ExecutionContextTypeName,
|
||||
CSharpTagHelperCodeRenderer.ExecutionContextVariableName,
|
||||
|
|
|
|||
|
|
@ -113,10 +113,6 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
|||
{
|
||||
Visit((ChunkBlock)chunk);
|
||||
}
|
||||
else if (chunk is SessionStateChunk)
|
||||
{
|
||||
Visit((SessionStateChunk)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(SetLayoutChunk 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(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);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return StartChunkBlock<T>(association, topLevel: false);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// 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.Globalization;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||
{
|
||||
public class LineMapping
|
||||
|
|
@ -40,5 +42,10 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
|||
{
|
||||
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.
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||
|
|
@ -37,6 +38,16 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
|||
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)
|
||||
{
|
||||
return left.Equals(right);
|
||||
|
|
|
|||
|
|
@ -17,9 +17,15 @@ namespace Microsoft.AspNet.Razor.Generator
|
|||
RunnerRunAsyncMethodName = "RunAsync";
|
||||
ScopeManagerBeginMethodName = "Begin";
|
||||
ScopeManagerEndMethodName = "End";
|
||||
OutputContentSetPropertyName = "ContentSet";
|
||||
OutputGenerateStartTagMethodName = "GenerateStartTag";
|
||||
OutputGeneratePreContentMethodName = "GeneratePreContent";
|
||||
OutputGenerateContentMethodName = "GenerateContent";
|
||||
OutputGeneratePostContentMethodName = "GeneratePostContent";
|
||||
OutputGenerateEndTagMethodName = "GenerateEndTag";
|
||||
ExecutionContextChildContentRetrievedPropertyName = "ChildContentRetrieved";
|
||||
ExecutionContextExecuteChildContentAsyncMethodName = "ExecuteChildContentAsync";
|
||||
ExecutionContextGetChildContentAsyncMethodName = "GetChildContentAsync";
|
||||
ExecutionContextAddMethodName = "Add";
|
||||
ExecutionContextAddTagHelperAttributeMethodName = "AddTagHelperAttribute";
|
||||
ExecutionContextAddHtmlAttributeMethodName = "AddHtmlAttribute";
|
||||
|
|
@ -51,21 +57,52 @@ namespace Microsoft.AspNet.Razor.Generator
|
|||
/// </summary>
|
||||
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>
|
||||
/// The name of the method used to generate a tag helper output's start tag.
|
||||
/// </summary>
|
||||
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>
|
||||
/// The name of the method used to generate a tag helper output's content.
|
||||
/// </summary>
|
||||
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>
|
||||
/// The name of the method used to generate a tag helper output's end tag.
|
||||
/// </summary>
|
||||
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>
|
||||
/// The name of the <see cref="ExecutionContextTypeName"/> method used to add tag helper attributes.
|
||||
/// </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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Parser.TagHelpers;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Generator
|
||||
{
|
||||
|
|
@ -60,10 +62,13 @@ namespace Microsoft.AspNet.Razor.Generator
|
|||
attribute.Value.Accept(codeGenerator);
|
||||
|
||||
var chunks = codeGenerator.Context.CodeTreeBuilder.CodeTree.Chunks;
|
||||
var first = chunks.FirstOrDefault();
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ namespace Microsoft.AspNet.Razor
|
|||
[NotNull] CodeTree codeTree)
|
||||
: this(parserResults.Document,
|
||||
parserResults.TagHelperDescriptors,
|
||||
parserResults.ParserErrors,
|
||||
parserResults.ErrorSink,
|
||||
codeBuilderResult,
|
||||
codeTree)
|
||||
{
|
||||
|
|
@ -34,35 +35,21 @@ namespace Microsoft.AspNet.Razor
|
|||
/// Instantiates a new <see cref="GeneratorResults"/> instance.
|
||||
/// </summary>
|
||||
/// <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="tagHelperDescriptors">
|
||||
/// 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="codeTree">A <see cref="CodeTree"/> for the document.</param>
|
||||
public GeneratorResults([NotNull] Block document,
|
||||
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
||||
[NotNull] IList<RazorError> parserErrors,
|
||||
[NotNull] ParserErrorSink errorSink,
|
||||
[NotNull] CodeBuilderResult codeBuilderResult,
|
||||
[NotNull] CodeTree codeTree)
|
||||
: this(parserErrors.Count == 0, document, tagHelperDescriptors, parserErrors, codeBuilderResult, codeTree)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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)
|
||||
: base(document, tagHelperDescriptors, errorSink)
|
||||
{
|
||||
GeneratedCode = codeBuilderResult.Code;
|
||||
DesignTimeLineMappings = codeBuilderResult.DesignTimeLineMappings;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
MapDirectives(SectionDirective, SyntaxConstants.CSharp.SectionKeyword);
|
||||
MapDirectives(HelperDirective, SyntaxConstants.CSharp.HelperKeyword);
|
||||
MapDirectives(LayoutDirective, SyntaxConstants.CSharp.LayoutKeyword);
|
||||
MapDirectives(SessionStateDirective, SyntaxConstants.CSharp.SessionStateKeyword);
|
||||
}
|
||||
|
||||
protected virtual void AddTagHelperDirective()
|
||||
|
|
@ -58,65 +57,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
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.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "C# Keywords are always lower-case")]
|
||||
protected virtual void HelperDirective()
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
"namespace",
|
||||
"class",
|
||||
"layout",
|
||||
"sessionstate"
|
||||
};
|
||||
|
||||
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
|
||||
// for identifying TagHelperDescriptors and rebuilding ParserResults.
|
||||
tagHelperDescriptors: Enumerable.Empty<TagHelperDescriptor>(),
|
||||
parserErrors: _errorSink.Errors.ToList());
|
||||
errorSink: _errorSink);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
}
|
||||
|
||||
// Return the new result
|
||||
return new ParserResults(syntaxTree, descriptors, errorSink.Errors.ToList());
|
||||
return new ParserResults(syntaxTree, descriptors, errorSink);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
public static readonly string NamespaceKeyword = "namespace";
|
||||
public static readonly string ClassKeyword = "class";
|
||||
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.Linq;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.Internal.Web.Utils;
|
||||
|
||||
|
|
@ -27,6 +28,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
|||
: base(source.Type, source.Children, source.CodeGenerator)
|
||||
{
|
||||
TagName = source.TagName;
|
||||
Descriptors = source.Descriptors;
|
||||
Attributes = new Dictionary<string, SyntaxTreeNode>(source.Attributes);
|
||||
_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>
|
||||
/// The HTML attributes.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
// 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
|
||||
{
|
||||
|
|
@ -18,7 +15,7 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
|||
public class TagHelperBlockBuilder : BlockBuilder
|
||||
{
|
||||
/// <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"/>.
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
TagName = original.TagName;
|
||||
Descriptors = original.Descriptors;
|
||||
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"/>.
|
||||
/// </summary>
|
||||
/// <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
|
||||
/// tag.</param>
|
||||
/// <param name="startTag">The <see cref="Block"/> that contains all information about the start
|
||||
/// of the HTML element.</param>
|
||||
public TagHelperBlockBuilder(string tagName, IEnumerable<TagHelperDescriptor> descriptors, Block startTag)
|
||||
public TagHelperBlockBuilder(string tagName,
|
||||
SourceLocation start,
|
||||
IDictionary<string, SyntaxTreeNode> attributes,
|
||||
IEnumerable<TagHelperDescriptor> descriptors)
|
||||
{
|
||||
TagName = tagName;
|
||||
Start = start;
|
||||
Descriptors = descriptors;
|
||||
Type = BlockType.Tag;
|
||||
CodeGenerator = new TagHelperCodeGenerator(descriptors);
|
||||
Type = startTag.Type;
|
||||
Attributes = GetTagAttributes(startTag, descriptors);
|
||||
|
||||
// There will always be at least one child for the '<'.
|
||||
Start = startTag.Children.First().Start;
|
||||
Attributes = new Dictionary<string, SyntaxTreeNode>(attributes);
|
||||
}
|
||||
|
||||
// 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>
|
||||
/// The HTML attributes.
|
||||
/// </summary>
|
||||
|
|
@ -106,280 +111,5 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
|||
/// The starting <see cref="SourceLocation"/> of the tag helper.
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
RewriteTags(context.SyntaxTree);
|
||||
|
||||
ValidateRewrittenSyntaxTree(context);
|
||||
RewriteTags(context.SyntaxTree, context);
|
||||
|
||||
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).
|
||||
TrackBlock(new BlockBuilder
|
||||
|
|
@ -43,6 +41,8 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
CodeGenerator = input.CodeGenerator
|
||||
});
|
||||
|
||||
var activeTagHelpers = _tagStack.Count;
|
||||
|
||||
foreach (var child in input.Children)
|
||||
{
|
||||
if (child.IsBlock)
|
||||
|
|
@ -51,65 +51,18 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
|
||||
if (childBlock.Type == BlockType.Tag)
|
||||
{
|
||||
// TODO: Fully handle malformed tags: https://github.com/aspnet/Razor/issues/104
|
||||
|
||||
// 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)
|
||||
if (TryRewriteTagHelper(childBlock, context))
|
||||
{
|
||||
_currentBlock.Children.Add(child);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsEndTag(childBlock))
|
||||
{
|
||||
// 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.
|
||||
// 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
|
||||
{
|
||||
// We're not an Html tag so iterate through children recursively.
|
||||
RewriteTags(childBlock);
|
||||
RewriteTags(childBlock, context);
|
||||
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
|
||||
// tag helper.
|
||||
|
||||
// Add the child to current block.
|
||||
// Add the child to current block.
|
||||
_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();
|
||||
}
|
||||
|
||||
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
|
||||
// the document, that's the only way we can have a non-zero _blockStack.Count.
|
||||
if (_blockStack.Count != 0)
|
||||
// TODO: Fully handle malformed tags: https://github.com/aspnet/Razor/issues/104
|
||||
|
||||
// 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
|
||||
// malformed.
|
||||
var candidateChildren = _currentBlock.Children.Reverse();
|
||||
var malformedTagHelper = candidateChildren.OfType<TagHelperBlock>().FirstOrDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the malformed tag helper is null that means something other than a TagHelper caused the
|
||||
// unbalancing of the syntax tree (should never happen).
|
||||
Debug.Assert(malformedTagHelper != null);
|
||||
var descriptors = Enumerable.Empty<TagHelperDescriptor>();
|
||||
|
||||
// We only create a single error because we can't reasonably determine other invalid tag helpers in the
|
||||
// document; having one malformed tag helper puts the document into an invalid state.
|
||||
context.ErrorSink.OnError(
|
||||
malformedTagHelper.Start,
|
||||
RazorResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper(
|
||||
malformedTagHelper.TagName));
|
||||
if (IsPotentialTagHelper(tagName, tagBlock))
|
||||
{
|
||||
descriptors = _provider.GetTagHelpers(tagName);
|
||||
}
|
||||
|
||||
// We need to build the remaining blocks in the stack to ensure we don't return an invalid syntax tree.
|
||||
do
|
||||
// If there aren't any TagHelperDescriptors registered then we aren't a TagHelper
|
||||
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();
|
||||
}
|
||||
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()
|
||||
|
|
@ -216,6 +268,52 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
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)
|
||||
{
|
||||
var child = tagBlock.Children.First();
|
||||
|
|
@ -240,9 +338,9 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
{
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
|
||||
|
|
@ -15,15 +17,18 @@ namespace Microsoft.AspNet.Razor
|
|||
/// <summary>
|
||||
/// Instantiates a new <see cref="ParserResults"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="document">The Razor syntax tree.</param>
|
||||
/// <param name="tagHelperDescriptors"><see cref="TagHelperDescriptor"/>s that apply to the current Razor
|
||||
/// document.</param>
|
||||
/// <param name="parserErrors"><see cref="RazorError"/>s encountered when parsing the current Razor
|
||||
/// document.</param>
|
||||
/// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
|
||||
/// <param name="tagHelperDescriptors">
|
||||
/// 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>
|
||||
public ParserResults([NotNull] Block document,
|
||||
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
||||
[NotNull] IList<RazorError> parserErrors)
|
||||
: this(parserErrors == null || parserErrors.Count == 0, document, tagHelperDescriptors, parserErrors)
|
||||
[NotNull] ParserErrorSink errorSink)
|
||||
: this(!errorSink.Errors.Any(), document, tagHelperDescriptors, errorSink)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -31,40 +36,50 @@ namespace Microsoft.AspNet.Razor
|
|||
/// Instantiates a new <see cref="ParserResults"/> instance.
|
||||
/// </summary>
|
||||
/// <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="tagHelperDescriptors"><see cref="TagHelperDescriptor"/>s that apply to the current Razor
|
||||
/// document.</param>
|
||||
/// <param name="errors"><see cref="RazorError"/>s encountered when parsing the current Razor
|
||||
/// document.</param>
|
||||
/// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
|
||||
/// <param name="tagHelperDescriptors">
|
||||
/// 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>
|
||||
protected ParserResults(bool success,
|
||||
[NotNull] Block document,
|
||||
[NotNull] IEnumerable<TagHelperDescriptor> tagHelperDescriptors,
|
||||
[NotNull] IList<RazorError> errors)
|
||||
[NotNull] ParserErrorSink errorSink)
|
||||
{
|
||||
Success = success;
|
||||
Document = document;
|
||||
TagHelperDescriptors = tagHelperDescriptors;
|
||||
ParserErrors = errors ?? new List<RazorError>();
|
||||
ErrorSink = errorSink;
|
||||
ParserErrors = errorSink.Errors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if parsing was successful (no errors)
|
||||
/// Indicates if parsing was successful (no errors).
|
||||
/// </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>
|
||||
/// The root node in the document's syntax tree
|
||||
/// The root node in the document's syntax tree.
|
||||
/// </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>
|
||||
/// The list of errors which occurred during parsing.
|
||||
/// </summary>
|
||||
public IList<RazorError> ParserErrors { get; private set; }
|
||||
public IEnumerable<RazorError> ParserErrors { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TagHelperDescriptor"/>s found for the current Razor document.
|
||||
/// </summary>
|
||||
public IEnumerable<TagHelperDescriptor> TagHelperDescriptors { get; private set; }
|
||||
public IEnumerable<TagHelperDescriptor> TagHelperDescriptors { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
/// <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:
|
||||
///
|
||||
///
|
||||
/// @if(isLoggedIn) {
|
||||
/// <p>Hello, @user!</p>
|
||||
/// }
|
||||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
/// <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:
|
||||
///
|
||||
///
|
||||
/// @if(isLoggedIn) {
|
||||
/// <p>Hello, @user!</p>
|
||||
/// }
|
||||
|
|
@ -228,7 +228,7 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
/// <summary>
|
||||
/// Sections cannot be empty. The "@section" keyword must be followed by a block of markup surrounded by "{}". For example:
|
||||
///
|
||||
///
|
||||
/// @section Sidebar {
|
||||
/// <!-- Markup and text goes here -->
|
||||
/// }
|
||||
|
|
@ -240,7 +240,7 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
/// <summary>
|
||||
/// Sections cannot be empty. The "@section" keyword must be followed by a block of markup surrounded by "{}". For example:
|
||||
///
|
||||
///
|
||||
/// @section Sidebar {
|
||||
/// <!-- Markup and text goes here -->
|
||||
/// }
|
||||
|
|
@ -252,7 +252,7 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
/// <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:
|
||||
///
|
||||
///
|
||||
/// @using System.Drawing;
|
||||
/// @{
|
||||
/// // OK here to use types from System.Drawing in the page.
|
||||
|
|
@ -265,7 +265,7 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
/// <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:
|
||||
///
|
||||
///
|
||||
/// @using System.Drawing;
|
||||
/// @{
|
||||
/// // OK here to use types from System.Drawing in the page.
|
||||
|
|
@ -278,12 +278,12 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
/// <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:
|
||||
///
|
||||
///
|
||||
/// @if(isLoggedIn)
|
||||
/// <p>Hello, @user</p>
|
||||
///
|
||||
///
|
||||
/// Instead, wrap the contents of the block in "{{}}":
|
||||
///
|
||||
///
|
||||
/// @if(isLoggedIn) {{
|
||||
/// <p>Hello, @user</p>
|
||||
/// }}
|
||||
|
|
@ -295,12 +295,12 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
/// <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:
|
||||
///
|
||||
///
|
||||
/// @if(isLoggedIn)
|
||||
/// <p>Hello, @user</p>
|
||||
///
|
||||
///
|
||||
/// Instead, wrap the contents of the block in "{{}}":
|
||||
///
|
||||
///
|
||||
/// @if(isLoggedIn) {{
|
||||
/// <p>Hello, @user</p>
|
||||
/// }}
|
||||
|
|
@ -390,38 +390,6 @@ namespace Microsoft.AspNet.Razor
|
|||
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>
|
||||
/// @section Header { ... }
|
||||
/// </summary>
|
||||
|
|
@ -454,22 +422,6 @@ namespace Microsoft.AspNet.Razor
|
|||
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>
|
||||
/// 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>
|
||||
|
|
@ -998,22 +950,6 @@ namespace Microsoft.AspNet.Razor
|
|||
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>
|
||||
/// Unexpected "{" after "@" character. Once inside the body of a code block (@if {}, @{}, etc.) you do not need to use "@{" to switch to code.
|
||||
/// </summary>
|
||||
|
|
@ -1142,38 +1078,6 @@ namespace Microsoft.AspNet.Razor
|
|||
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>
|
||||
/// [BG][{0}] Shutdown
|
||||
/// </summary>
|
||||
|
|
@ -1431,7 +1335,7 @@ namespace Microsoft.AspNet.Razor
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tag Helper attributes must have a name.
|
||||
/// Tag Helper '{0}'s attributes must have names.
|
||||
/// </summary>
|
||||
internal static string TagHelpers_AttributesMustHaveAName
|
||||
{
|
||||
|
|
@ -1439,15 +1343,15 @@ namespace Microsoft.AspNet.Razor
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tag Helper attributes must have a name.
|
||||
/// Tag Helper '{0}'s attributes must have names.
|
||||
/// </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>
|
||||
/// 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>
|
||||
internal static string TagHelpers_CannotHaveCSharpInTagDeclaration
|
||||
{
|
||||
|
|
@ -1455,11 +1359,11 @@ namespace Microsoft.AspNet.Razor
|
|||
}
|
||||
|
||||
/// <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>
|
||||
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>
|
||||
|
|
@ -1478,22 +1382,6 @@ namespace Microsoft.AspNet.Razor
|
|||
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>
|
||||
/// Directive '{0}' must have a value.
|
||||
/// </summary>
|
||||
|
|
@ -1542,6 +1430,106 @@ namespace Microsoft.AspNet.Razor
|
|||
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)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</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>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
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
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
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
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
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
|
||||
: 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">
|
||||
<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 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">
|
||||
<value>@section Header { ... }</value>
|
||||
<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">
|
||||
<value>"<text>" and "</text>" tags cannot contain attributes.</value>
|
||||
</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">
|
||||
<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>
|
||||
|
|
@ -321,9 +312,6 @@ Instead, wrap the contents of the block in "{{}}":
|
|||
<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>
|
||||
</data>
|
||||
<data name="ParseError_Unexpected" xml:space="preserve">
|
||||
<value>Unexpected "{0}"</value>
|
||||
</data>
|
||||
<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>
|
||||
</data>
|
||||
|
|
@ -348,13 +336,6 @@ Instead, wrap the contents of the block in "{{}}":
|
|||
<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>
|
||||
</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">
|
||||
<value>[BG][{0}] Shutdown</value>
|
||||
</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>
|
||||
</data>
|
||||
<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 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 name="TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock" xml:space="preserve">
|
||||
<value>A TagHelperCodeGenerator must only be used with TagHelperBlocks.</value>
|
||||
</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">
|
||||
<value>Directive '{0}' must have a value.</value>
|
||||
</data>
|
||||
|
|
@ -424,4 +402,24 @@ Instead, wrap the contents of the block in "{{}}":
|
|||
<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>
|
||||
</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>
|
||||
|
|
@ -252,7 +252,7 @@ namespace Microsoft.AspNet.Razor
|
|||
generator.DesignTimeMode = Host.DesignTimeMode;
|
||||
generator.Visit(results);
|
||||
|
||||
var codeBuilderContext = new CodeBuilderContext(generator.Context);
|
||||
var codeBuilderContext = new CodeBuilderContext(generator.Context, results.ErrorSink);
|
||||
codeBuilderContext.Checksum = checksum;
|
||||
var builder = CreateCodeBuilder(codeBuilderContext);
|
||||
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
|
||||
/// helper's property. Last value written should not be or end with a semicolon.
|
||||
/// </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="context">A <see cref="CodeGeneratorContext"/> instance that contains information about
|
||||
/// 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,
|
||||
[NotNull] CSharpCodeWriter writer,
|
||||
[NotNull] CodeBuilderContext context,
|
||||
[NotNull] Action<CSharpCodeWriter> renderAttributeValue)
|
||||
[NotNull] Action<CSharpCodeWriter> renderAttributeValue,
|
||||
bool complexValue)
|
||||
{
|
||||
renderAttributeValue(writer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,12 +16,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
/// </summary>
|
||||
internal TagHelperDescriptor([NotNull] string tagName,
|
||||
[NotNull] string typeName,
|
||||
[NotNull] string assemblyName,
|
||||
ContentBehavior contentBehavior)
|
||||
[NotNull] string assemblyName)
|
||||
: this(tagName,
|
||||
typeName,
|
||||
assemblyName,
|
||||
contentBehavior,
|
||||
Enumerable.Empty<TagHelperAttributeDescriptor>())
|
||||
{
|
||||
}
|
||||
|
|
@ -34,21 +32,17 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
/// <see cref="TagHelperDescriptor"/> which applies to every HTML tag.</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="contentBehavior">The <see cref="TagHelpers.ContentBehavior"/>
|
||||
/// of the tag helper.</param>
|
||||
/// <param name="attributes">
|
||||
/// The <see cref="TagHelperAttributeDescriptor"/>s to request from the HTML tag.
|
||||
/// </param>
|
||||
public TagHelperDescriptor([NotNull] string tagName,
|
||||
[NotNull] string typeName,
|
||||
[NotNull] string assemblyName,
|
||||
ContentBehavior contentBehavior,
|
||||
[NotNull] IEnumerable<TagHelperAttributeDescriptor> attributes)
|
||||
{
|
||||
TagName = tagName;
|
||||
TypeName = typeName;
|
||||
AssemblyName = assemblyName;
|
||||
ContentBehavior = contentBehavior;
|
||||
Attributes = new List<TagHelperAttributeDescriptor>(attributes);
|
||||
}
|
||||
|
||||
|
|
@ -67,11 +61,6 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
/// </summary>
|
||||
public string AssemblyName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TagHelpers.ContentBehavior"/> of the tag helper.
|
||||
/// </summary>
|
||||
public ContentBehavior ContentBehavior { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of attributes the tag helper expects.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -29,15 +29,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
/// <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// Determines equality based on <see cref="TagHelperDescriptor.TypeName"/>,
|
||||
/// <see cref="TagHelperDescriptor.AssemblyName"/>, <see cref="TagHelperDescriptor.TagName"/> and
|
||||
/// <see cref="TagHelperDescriptor.ContentBehavior"/>.
|
||||
/// <see cref="TagHelperDescriptor.AssemblyName"/> and <see cref="TagHelperDescriptor.TagName"/>.
|
||||
/// </remarks>
|
||||
public bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
||||
{
|
||||
return string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal) &&
|
||||
string.Equals(descriptorX.TagName, descriptorY.TagName, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(descriptorX.AssemblyName, descriptorY.AssemblyName, StringComparison.Ordinal) &&
|
||||
descriptorX.ContentBehavior == descriptorY.ContentBehavior;
|
||||
string.Equals(descriptorX.AssemblyName, descriptorY.AssemblyName, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -51,7 +49,6 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
.Add(descriptor.TagName, StringComparer.OrdinalIgnoreCase)
|
||||
.Add(descriptor.TypeName, StringComparer.Ordinal)
|
||||
.Add(descriptor.AssemblyName, StringComparer.Ordinal)
|
||||
.Add(descriptor.ContentBehavior)
|
||||
.CombinedHash;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@
|
|||
"System.Collections": "4.0.10-beta-*",
|
||||
"System.Diagnostics.Debug": "4.0.10-beta-*",
|
||||
"System.Diagnostics.Tools": "4.0.0-beta-*",
|
||||
"System.IO": "4.0.10-beta-*",
|
||||
"System.IO.FileSystem": "4.0.0-beta-*",
|
||||
"System.Linq": "4.0.0-beta-*",
|
||||
"System.Reflection": "4.0.10-beta-*",
|
||||
"System.Resources.ResourceManager": "4.0.0-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.Thread": "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.
|
||||
// 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.TagHelpers;
|
||||
|
|
@ -20,6 +21,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
bool IEqualityComparer<TagHelperDescriptor>.Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
||||
{
|
||||
return base.Equals(descriptorX, descriptorY) &&
|
||||
// Tests should be exact casing
|
||||
string.Equals(descriptorX.TagName, descriptorY.TagName, StringComparison.Ordinal) &&
|
||||
descriptorX.Attributes.SequenceEqual(descriptorY.Attributes,
|
||||
CompleteTagHelperAttributeDescriptorComparer.Default);
|
||||
}
|
||||
|
|
@ -43,17 +46,17 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
|
||||
public bool Equals(TagHelperAttributeDescriptor descriptorX, TagHelperAttributeDescriptor descriptorY)
|
||||
{
|
||||
return descriptorX.Name == descriptorY.Name &&
|
||||
descriptorX.PropertyName == descriptorY.PropertyName &&
|
||||
descriptorX.TypeName == descriptorY.TypeName;
|
||||
return string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.Ordinal) &&
|
||||
string.Equals(descriptorX.PropertyName, descriptorY.PropertyName, StringComparison.Ordinal) &&
|
||||
string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode(TagHelperAttributeDescriptor descriptor)
|
||||
{
|
||||
return HashCodeCombiner.Start()
|
||||
.Add(descriptor.Name)
|
||||
.Add(descriptor.PropertyName)
|
||||
.Add(descriptor.TypeName)
|
||||
.Add(descriptor.Name, StringComparer.Ordinal)
|
||||
.Add(descriptor.PropertyName, StringComparer.Ordinal)
|
||||
.Add(descriptor.TypeName, StringComparer.Ordinal)
|
||||
.CombinedHash;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Reflection;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
using Xunit;
|
||||
|
|
@ -12,6 +13,42 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
private static readonly string AssemblyName =
|
||||
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]
|
||||
public void CreateDescriptor_OverridesAttributeNameFromAttribute()
|
||||
{
|
||||
|
|
@ -22,10 +59,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
nameof(OverriddenAttributeTagHelper.ValidAttribute2));
|
||||
var expectedDescriptors = new[] {
|
||||
new TagHelperDescriptor(
|
||||
"OverriddenAttribute",
|
||||
"overridden-attribute",
|
||||
typeof(OverriddenAttributeTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor("SomethingElse", validProperty1),
|
||||
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
||||
|
|
@ -49,12 +85,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
nameof(InheritedOverriddenAttributeTagHelper.ValidAttribute2));
|
||||
var expectedDescriptors = new[] {
|
||||
new TagHelperDescriptor(
|
||||
"InheritedOverriddenAttribute",
|
||||
"inherited-overridden-attribute",
|
||||
typeof(InheritedOverriddenAttributeTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor(nameof(InheritedOverriddenAttributeTagHelper.ValidAttribute1),
|
||||
new TagHelperAttributeDescriptor("valid-attribute1",
|
||||
validProperty1),
|
||||
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
||||
})
|
||||
|
|
@ -77,10 +112,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
nameof(InheritedNotOverriddenAttributeTagHelper.ValidAttribute2));
|
||||
var expectedDescriptors = new[] {
|
||||
new TagHelperDescriptor(
|
||||
"InheritedNotOverriddenAttribute",
|
||||
"inherited-not-overridden-attribute",
|
||||
typeof(InheritedNotOverriddenAttributeTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor("SomethingElse", validProperty1),
|
||||
new TagHelperAttributeDescriptor("Something-Else", validProperty2)
|
||||
|
|
@ -100,7 +134,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
// Arrange
|
||||
var objectAssemblyName = typeof(object).GetTypeInfo().Assembly.GetName().Name;
|
||||
var expectedDescriptor =
|
||||
new TagHelperDescriptor("Object", "System.Object", objectAssemblyName, ContentBehavior.None);
|
||||
new TagHelperDescriptor("object", "System.Object", objectAssemblyName);
|
||||
|
||||
// Act
|
||||
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(object));
|
||||
|
|
@ -117,12 +151,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var intProperty = typeof(InheritedSingleAttributeTagHelper).GetProperty(
|
||||
nameof(InheritedSingleAttributeTagHelper.IntAttribute));
|
||||
var expectedDescriptor = new TagHelperDescriptor(
|
||||
"InheritedSingleAttribute",
|
||||
"inherited-single-attribute",
|
||||
typeof(InheritedSingleAttributeTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor(nameof(InheritedSingleAttributeTagHelper.IntAttribute), intProperty)
|
||||
new TagHelperAttributeDescriptor("int-attribute", intProperty)
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -139,12 +172,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
// Arrange
|
||||
var intProperty = typeof(SingleAttributeTagHelper).GetProperty(nameof(SingleAttributeTagHelper.IntAttribute));
|
||||
var expectedDescriptor = new TagHelperDescriptor(
|
||||
"SingleAttribute",
|
||||
"single-attribute",
|
||||
typeof(SingleAttributeTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor(nameof(SingleAttributeTagHelper.IntAttribute), intProperty)
|
||||
new TagHelperAttributeDescriptor("int-attribute", intProperty)
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -162,12 +194,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var validProperty = typeof(MissingAccessorTagHelper).GetProperty(
|
||||
nameof(MissingAccessorTagHelper.ValidAttribute));
|
||||
var expectedDescriptor = new TagHelperDescriptor(
|
||||
"MissingAccessor",
|
||||
"missing-accessor",
|
||||
typeof(MissingAccessorTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor(nameof(MissingAccessorTagHelper.ValidAttribute), validProperty)
|
||||
new TagHelperAttributeDescriptor("valid-attribute", validProperty)
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -185,13 +216,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var validProperty = typeof(PrivateAccessorTagHelper).GetProperty(
|
||||
nameof(PrivateAccessorTagHelper.ValidAttribute));
|
||||
var expectedDescriptor = new TagHelperDescriptor(
|
||||
"PrivateAccessor",
|
||||
"private-accessor",
|
||||
typeof(PrivateAccessorTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor(
|
||||
nameof(PrivateAccessorTagHelper.ValidAttribute), validProperty)
|
||||
"valid-attribute", validProperty)
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -202,43 +232,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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]
|
||||
public void CreateDescriptor_ResolvesMultipleTagHelperDescriptorsFromSingleType()
|
||||
{
|
||||
|
|
@ -249,17 +242,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
"div",
|
||||
typeof(MultiTagTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor(nameof(MultiTagTagHelper.ValidAttribute), validProp)
|
||||
new TagHelperAttributeDescriptor("valid-attribute", validProp)
|
||||
}),
|
||||
new TagHelperDescriptor(
|
||||
"p",
|
||||
typeof(MultiTagTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor(nameof(MultiTagTagHelper.ValidAttribute), validProp)
|
||||
new TagHelperAttributeDescriptor("valid-attribute", validProp)
|
||||
})
|
||||
};
|
||||
|
||||
|
|
@ -276,12 +267,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
// Arrange
|
||||
var validProp = typeof(InheritedMultiTagTagHelper).GetProperty(nameof(InheritedMultiTagTagHelper.ValidAttribute));
|
||||
var expectedDescriptor = new TagHelperDescriptor(
|
||||
"InheritedMultiTag",
|
||||
"inherited-multi-tag",
|
||||
typeof(InheritedMultiTagTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None,
|
||||
new[] {
|
||||
new TagHelperAttributeDescriptor(nameof(InheritedMultiTagTagHelper.ValidAttribute), validProp)
|
||||
new TagHelperAttributeDescriptor("valid-attribute", validProp)
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -300,13 +290,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
new TagHelperDescriptor(
|
||||
"p",
|
||||
typeof(DuplicateTagNameTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None),
|
||||
AssemblyName),
|
||||
new TagHelperDescriptor(
|
||||
"div",
|
||||
typeof(DuplicateTagNameTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None)
|
||||
AssemblyName)
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -323,8 +311,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var expectedDescriptors = new[] {
|
||||
new TagHelperDescriptor("data-condition",
|
||||
typeof(OverrideNameTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None),
|
||||
AssemblyName),
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -342,18 +329,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
new TagHelperDescriptor(
|
||||
"span",
|
||||
typeof(MultipleAttributeTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None),
|
||||
AssemblyName),
|
||||
new TagHelperDescriptor(
|
||||
"p",
|
||||
typeof(MultipleAttributeTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None),
|
||||
AssemblyName),
|
||||
new TagHelperDescriptor(
|
||||
"div",
|
||||
typeof(MultipleAttributeTagHelper).FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None)
|
||||
AssemblyName)
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -363,16 +347,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
Assert.Equal(expectedDescriptors, descriptors, CompleteTagHelperDescriptorComparer.Default);
|
||||
}
|
||||
|
||||
[ContentBehavior(ContentBehavior.Append)]
|
||||
private class CustomContentBehaviorTagHelper
|
||||
{
|
||||
}
|
||||
|
||||
private class InheritedCustomContentBehaviorTagHelper : CustomContentBehaviorTagHelper
|
||||
{
|
||||
}
|
||||
|
||||
[TagName("p", "div")]
|
||||
[HtmlElementName("p", "div")]
|
||||
private class MultiTagTagHelper
|
||||
{
|
||||
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
|
||||
{
|
||||
}
|
||||
|
||||
[TagName("data-condition")]
|
||||
[HtmlElementName("data-condition")]
|
||||
private class OverrideNameTagHelper
|
||||
{
|
||||
}
|
||||
|
||||
[TagName("span")]
|
||||
[TagName("div", "p")]
|
||||
[HtmlElementName("span")]
|
||||
[HtmlElementName("div", "p")]
|
||||
private class MultipleAttributeTagHelper
|
||||
{
|
||||
}
|
||||
|
|
@ -419,5 +394,41 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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
|
||||
{
|
||||
return new TagHelperDescriptor("Valid_Plain",
|
||||
return new TagHelperDescriptor("valid_plain",
|
||||
Valid_PlainTagHelperType.FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None);
|
||||
AssemblyName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,10 +35,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
{
|
||||
get
|
||||
{
|
||||
return new TagHelperDescriptor("Valid_Inherited",
|
||||
return new TagHelperDescriptor("valid_inherited",
|
||||
Valid_InheritedTagHelperType.FullName,
|
||||
AssemblyName,
|
||||
ContentBehavior.None);
|
||||
AssemblyName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,8 +73,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var stringTagHelperDescriptor =
|
||||
new TagHelperDescriptor("string",
|
||||
"System.String",
|
||||
assemblyB,
|
||||
ContentBehavior.None);
|
||||
assemblyB);
|
||||
|
||||
return new TheoryData<Dictionary<string, IEnumerable<Type>>, // descriptorAssemblyLookups
|
||||
IEnumerable<TagHelperDirectiveDescriptor>, // directiveDescriptors
|
||||
|
|
@ -230,8 +227,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var stringTagHelperDescriptor =
|
||||
new TagHelperDescriptor("string",
|
||||
"System.String",
|
||||
assemblyB,
|
||||
ContentBehavior.None);
|
||||
assemblyB);
|
||||
|
||||
return new TheoryData<Dictionary<string, IEnumerable<Type>>, // descriptorAssemblyLookups
|
||||
IEnumerable<TagHelperDirectiveDescriptor>> // directiveDescriptors
|
||||
|
|
@ -358,7 +354,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
// Arrange
|
||||
var tagHelperTypeResolver = new TestTagHelperTypeResolver(TestableTagHelpers)
|
||||
{
|
||||
OnGetLibraryDefinedTypes = (assemblyName) =>
|
||||
OnGetExportedTypes = (assemblyName) =>
|
||||
{
|
||||
Assert.Equal("MyAssembly", assemblyName.Name);
|
||||
}
|
||||
|
|
@ -523,7 +519,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
_lookupValues = lookupValues;
|
||||
}
|
||||
|
||||
internal override IEnumerable<TypeInfo> GetLibraryDefinedTypes(AssemblyName assemblyName)
|
||||
protected override IEnumerable<TypeInfo> GetExportedTypes(AssemblyName assemblyName)
|
||||
{
|
||||
IEnumerable<Type> types;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,76 @@
|
|||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||
{
|
||||
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
|
||||
{
|
||||
get
|
||||
|
|
|
|||
|
|
@ -9,39 +9,65 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
public class TagHelperOutputTest
|
||||
{
|
||||
[Fact]
|
||||
public void TagName_CannotSetToNullInCtor()
|
||||
public void TagName_CanSetToNullInCtor()
|
||||
{
|
||||
// Arrange & Act
|
||||
var tagHelperOutput = new TagHelperOutput(null);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(tagHelperOutput.TagName);
|
||||
Assert.Null(tagHelperOutput.TagName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TagName_CannotSetToNull()
|
||||
public void TagName_CanSetToNull()
|
||||
{
|
||||
// Arrange
|
||||
var tagHelperOutput = new TagHelperOutput("p");
|
||||
|
||||
// Act
|
||||
tagHelperOutput.TagName = null;
|
||||
// Arrange & Act
|
||||
var tagHelperOutput = new TagHelperOutput("p")
|
||||
{
|
||||
TagName = null
|
||||
};
|
||||
|
||||
// Assert
|
||||
Assert.Empty(tagHelperOutput.TagName);
|
||||
Assert.Null(tagHelperOutput.TagName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Content_CannotSetToNull()
|
||||
public void Content_CanSetToNull()
|
||||
{
|
||||
// Arrange
|
||||
var tagHelperOutput = new TagHelperOutput("p");
|
||||
|
||||
// Act
|
||||
tagHelperOutput.Content = null;
|
||||
// Arrange & Act
|
||||
var tagHelperOutput = new TagHelperOutput("p")
|
||||
{
|
||||
Content = null
|
||||
};
|
||||
|
||||
// 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]
|
||||
|
|
@ -119,9 +145,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
{
|
||||
{ "class", "btn" },
|
||||
{ "something", " spaced " }
|
||||
});
|
||||
|
||||
tagHelperOutput.SelfClosing = true;
|
||||
})
|
||||
{
|
||||
SelfClosing = true
|
||||
};
|
||||
|
||||
// Act
|
||||
var output = tagHelperOutput.GenerateStartTag();
|
||||
|
|
@ -135,9 +162,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
public void GenerateEndTag_ReturnsNothingIfWhitespaceTagName()
|
||||
{
|
||||
// Arrange
|
||||
var tagHelperOutput = new TagHelperOutput(" "); ;
|
||||
|
||||
tagHelperOutput.Content = "Hello World";
|
||||
var tagHelperOutput = new TagHelperOutput(" ")
|
||||
{
|
||||
Content = "Hello World"
|
||||
};
|
||||
|
||||
// Act
|
||||
var output = tagHelperOutput.GenerateEndTag();
|
||||
|
|
@ -146,13 +174,47 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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]
|
||||
public void GenerateContent_ReturnsContent()
|
||||
{
|
||||
// Arrange
|
||||
var tagHelperOutput = new TagHelperOutput("p");
|
||||
|
||||
tagHelperOutput.Content = "Hello World";
|
||||
var tagHelperOutput = new TagHelperOutput("p")
|
||||
{
|
||||
Content = "Hello World"
|
||||
};
|
||||
|
||||
// Act
|
||||
var output = tagHelperOutput.GenerateContent();
|
||||
|
|
@ -168,11 +230,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
// Arrange
|
||||
var tagHelperOutput = new TagHelperOutput("p")
|
||||
{
|
||||
SelfClosing = true
|
||||
SelfClosing = true,
|
||||
Content = "Hello World"
|
||||
};
|
||||
|
||||
tagHelperOutput.Content = "Hello World";
|
||||
|
||||
// Act
|
||||
var output = tagHelperOutput.GenerateContent();
|
||||
|
||||
|
|
@ -180,6 +241,39 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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]
|
||||
public void GenerateEndTag_ReturnsEndTag()
|
||||
{
|
||||
|
|
@ -209,6 +303,54 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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]
|
||||
[InlineData("class", "ClASs")]
|
||||
[InlineData("CLaSs", "class")]
|
||||
|
|
|
|||
|
|
@ -66,23 +66,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
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
|
||||
{
|
||||
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.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -9,6 +11,11 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
|||
{
|
||||
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]
|
||||
public void Begin_CreatesContextWithAppropriateTagName()
|
||||
{
|
||||
|
|
@ -16,7 +23,11 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
|||
var scopeManager = new TagHelperScopeManager();
|
||||
|
||||
// Act
|
||||
var executionContext = scopeManager.Begin("p");
|
||||
var executionContext = scopeManager.Begin("p",
|
||||
string.Empty,
|
||||
DefaultExecuteChildContentAsync,
|
||||
DefaultStartWritingScope,
|
||||
DefaultEndWritingScope);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("p", executionContext.TagName);
|
||||
|
|
@ -29,8 +40,16 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
|||
var scopeManager = new TagHelperScopeManager();
|
||||
|
||||
// Act
|
||||
var executionContext = scopeManager.Begin("p");
|
||||
executionContext = scopeManager.Begin("div");
|
||||
var executionContext = scopeManager.Begin("p",
|
||||
string.Empty,
|
||||
DefaultExecuteChildContentAsync,
|
||||
DefaultStartWritingScope,
|
||||
DefaultEndWritingScope);
|
||||
executionContext = scopeManager.Begin("div",
|
||||
string.Empty,
|
||||
DefaultExecuteChildContentAsync,
|
||||
DefaultStartWritingScope,
|
||||
DefaultEndWritingScope);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("div", executionContext.TagName);
|
||||
|
|
@ -43,8 +62,16 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
|||
var scopeManager = new TagHelperScopeManager();
|
||||
|
||||
// Act
|
||||
var executionContext = scopeManager.Begin("p");
|
||||
executionContext = scopeManager.Begin("div");
|
||||
var executionContext = scopeManager.Begin("p",
|
||||
string.Empty,
|
||||
DefaultExecuteChildContentAsync,
|
||||
DefaultStartWritingScope,
|
||||
DefaultEndWritingScope);
|
||||
executionContext = scopeManager.Begin("div",
|
||||
string.Empty,
|
||||
DefaultExecuteChildContentAsync,
|
||||
DefaultStartWritingScope,
|
||||
DefaultEndWritingScope);
|
||||
executionContext = scopeManager.End();
|
||||
|
||||
// Assert
|
||||
|
|
@ -58,8 +85,16 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
|||
var scopeManager = new TagHelperScopeManager();
|
||||
|
||||
// Act
|
||||
var executionContext = scopeManager.Begin("p");
|
||||
executionContext = scopeManager.Begin("div");
|
||||
var executionContext = scopeManager.Begin("p",
|
||||
string.Empty,
|
||||
DefaultExecuteChildContentAsync,
|
||||
DefaultStartWritingScope,
|
||||
DefaultEndWritingScope);
|
||||
executionContext = scopeManager.Begin("div",
|
||||
string.Empty,
|
||||
DefaultExecuteChildContentAsync,
|
||||
DefaultStartWritingScope,
|
||||
DefaultEndWritingScope);
|
||||
executionContext = scopeManager.End();
|
||||
executionContext = scopeManager.End();
|
||||
|
||||
|
|
@ -85,7 +120,6 @@ namespace Microsoft.AspNet.Razor.Runtime.Test.TagHelpers
|
|||
});
|
||||
|
||||
Assert.Equal(expectedError, ex.Message);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -114,14 +114,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
public TestTagHelperTypeResolver(IEnumerable<Type> assemblyTypes)
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,16 @@
|
|||
"dependencies": {
|
||||
"Microsoft.AspNet.Razor.Runtime": "4.0.0-*",
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
"Xunit.KRunner": "1.0.0-*"
|
||||
"xunit.runner.kre": "1.0.0-*"
|
||||
},
|
||||
"commands": {
|
||||
"test": "Xunit.KRunner"
|
||||
"test": "xunit.runner.kre"
|
||||
},
|
||||
"frameworks": {
|
||||
"aspnet50": { },
|
||||
"aspnetcore50": {
|
||||
"dependencies": {
|
||||
"System.Reflection.TypeExtensions": "4.0.0-beta-*",
|
||||
"System.Runtime.Extensions": "4.0.10-beta-*"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ namespace Microsoft.AspNet.Razor.Test
|
|||
"myclass",
|
||||
"myns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: false);
|
||||
shouldGenerateLinePragmas: false,
|
||||
errorSink: new ParserErrorSink());
|
||||
|
||||
// Act
|
||||
var generator = language.CreateCodeBuilder(codeBuilderContext);
|
||||
|
|
|
|||
|
|
@ -434,28 +434,30 @@ namespace Microsoft.AspNet.Razor.Test.Framework
|
|||
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
|
||||
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)));
|
||||
}
|
||||
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}",
|
||||
expectedErrors.Count,
|
||||
actualErrors.Count,
|
||||
realCount,
|
||||
FormatErrors(expectedErrors),
|
||||
FormatErrors(actualErrors)));
|
||||
Assert.Equal(expectedErrors.ToArray(), actualErrors.ToArray());
|
||||
Assert.Equal(expectedErrors, actualErrors);
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -300,11 +300,6 @@ namespace Microsoft.AspNet.Razor.Test.Framework
|
|||
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)
|
||||
{
|
||||
return _self.With(
|
||||
|
|
|
|||
|
|
@ -26,21 +26,18 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
new TagHelperDescriptor("p",
|
||||
"PTagHelper",
|
||||
"SomeAssembly",
|
||||
ContentBehavior.None,
|
||||
new [] {
|
||||
new TagHelperAttributeDescriptor("age", pAgePropertyInfo)
|
||||
}),
|
||||
new TagHelperDescriptor("input",
|
||||
"InputTagHelper",
|
||||
"SomeAssembly",
|
||||
ContentBehavior.None,
|
||||
new TagHelperAttributeDescriptor[] {
|
||||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
|
||||
}),
|
||||
new TagHelperDescriptor("input",
|
||||
"InputTagHelper2",
|
||||
"SomeAssembly",
|
||||
ContentBehavior.None,
|
||||
new TagHelperAttributeDescriptor[] {
|
||||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
|
||||
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
|
||||
{
|
||||
get
|
||||
|
|
@ -109,13 +91,6 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
Enumerable.Empty<TagHelperDescriptor>(),
|
||||
false
|
||||
},
|
||||
{
|
||||
"ContentBehaviorTagHelpers",
|
||||
"ContentBehaviorTagHelpers",
|
||||
ContentBehaviorTagHelperDescriptors,
|
||||
ContentBehaviorTagHelperDescriptors,
|
||||
false
|
||||
},
|
||||
{
|
||||
"ComplexTagHelpers",
|
||||
"ComplexTagHelpers",
|
||||
|
|
@ -144,7 +119,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
bool designTimeMode)
|
||||
{
|
||||
RunTagHelperTest(
|
||||
testName,
|
||||
testName,
|
||||
baseLineName: baselineName,
|
||||
tagHelperDescriptors: tagHelperDescriptors,
|
||||
onResults: (results) =>
|
||||
|
|
@ -174,7 +149,13 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
generatedAbsoluteIndex: 475,
|
||||
generatedLineIndex: 15,
|
||||
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,
|
||||
generatedLineIndex: 15,
|
||||
characterOffsetIndex: 14,
|
||||
contentLength: 11)
|
||||
}
|
||||
},
|
||||
{
|
||||
"ContentBehaviorTagHelpers",
|
||||
"ContentBehaviorTagHelpers.DesignTime",
|
||||
ContentBehaviorTagHelperDescriptors,
|
||||
new List<LineMapping>
|
||||
{
|
||||
BuildLineMapping(documentAbsoluteIndex: 14,
|
||||
documentLineIndex: 0,
|
||||
generatedAbsoluteIndex: 495,
|
||||
generatedLineIndex: 15,
|
||||
characterOffsetIndex: 14,
|
||||
contentLength: 11)
|
||||
contentLength: 11),
|
||||
BuildLineMapping(documentAbsoluteIndex: 189,
|
||||
documentLineIndex: 6,
|
||||
generatedAbsoluteIndex: 1574,
|
||||
generatedLineIndex: 44,
|
||||
characterOffsetIndex: 40,
|
||||
contentLength: 4)
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -213,17 +186,32 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
{
|
||||
BuildLineMapping(14, 0, 479, 15, 14, 11),
|
||||
BuildLineMapping(30, 2, 1, 995, 35, 0, 48),
|
||||
BuildLineMapping(157, 7, 32, 1177, 45, 6, 12),
|
||||
BuildLineMapping(205, 9, 1260, 50, 0, 12),
|
||||
BuildLineMapping(218, 9, 13, 1356, 56, 12, 27),
|
||||
BuildLineMapping(346, 12, 1754, 68, 0, 48),
|
||||
BuildLineMapping(440, 15, 46, 2004, 78, 6, 8),
|
||||
BuildLineMapping(501, 16, 31, 2384, 88, 6, 30),
|
||||
BuildLineMapping(568, 17, 30, 2733, 97, 0, 10),
|
||||
BuildLineMapping(601, 17, 63, 2815, 103, 0, 8),
|
||||
BuildLineMapping(632, 17, 94, 2895, 109, 0, 1),
|
||||
BuildLineMapping(639, 18, 3149, 118, 0, 15),
|
||||
BuildLineMapping(680, 21, 3234, 124, 0, 1)
|
||||
BuildLineMapping(205, 9, 1113, 44, 0, 12),
|
||||
BuildLineMapping(218, 9, 13, 1209, 50, 12, 27),
|
||||
BuildLineMapping(346, 12, 1607, 62, 0, 48),
|
||||
BuildLineMapping(440, 15, 46, 1798, 71, 6, 8),
|
||||
BuildLineMapping(457, 15, 2121, 79, 63, 4),
|
||||
BuildLineMapping(501, 16, 31, 2328, 86, 6, 30),
|
||||
BuildLineMapping(568, 17, 30, 2677, 95, 0, 10),
|
||||
BuildLineMapping(601, 17, 63, 2759, 101, 0, 8),
|
||||
BuildLineMapping(632, 17, 94, 2839, 107, 0, 1),
|
||||
BuildLineMapping(639, 18, 3093, 116, 0, 15),
|
||||
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 },
|
||||
{ "BasicTagHelpers", PAndInputTagHelperDescriptors },
|
||||
{ "BasicTagHelpers.RemoveTagHelper", PAndInputTagHelperDescriptors },
|
||||
{ "ContentBehaviorTagHelpers", ContentBehaviorTagHelperDescriptors },
|
||||
{ "ComplexTagHelpers", PAndInputTagHelperDescriptors },
|
||||
};
|
||||
}
|
||||
|
|
@ -312,7 +299,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
RunTagHelperTest("AddTagHelperDirective",
|
||||
designTimeMode: true,
|
||||
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",
|
||||
"MyTagHelper",
|
||||
"SomeAssembly",
|
||||
ContentBehavior.None,
|
||||
new [] {
|
||||
new TagHelperAttributeDescriptor("BoundProperty",
|
||||
propertyInfo)
|
||||
}),
|
||||
new TagHelperDescriptor("NestedTagHelper", "NestedTagHelper", "SomeAssembly", ContentBehavior.Modify)
|
||||
new TagHelperDescriptor("NestedTagHelper", "NestedTagHelper", "SomeAssembly")
|
||||
};
|
||||
|
||||
// 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
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Utils;
|
||||
using Moq;
|
||||
|
|
@ -23,7 +24,8 @@ namespace Microsoft.AspNet.Razor.Test.Generator.CodeTree
|
|||
"TestClass",
|
||||
"TestNamespace",
|
||||
"Foo.cs",
|
||||
shouldGenerateLinePragmas: false);
|
||||
shouldGenerateLinePragmas: false,
|
||||
errorSink: new ParserErrorSink());
|
||||
codeBuilderContext.CodeTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode.Object);
|
||||
codeBuilderContext.CodeTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode.Object);
|
||||
var codeBuilder = language.CreateCodeBuilder(codeBuilderContext);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#if !ASPNETCORE50
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
using Xunit;
|
||||
|
|
@ -34,7 +35,8 @@ namespace Microsoft.AspNet.Razor
|
|||
"myclass",
|
||||
"myns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: false);
|
||||
shouldGenerateLinePragmas: false,
|
||||
errorSink: new ParserErrorSink());
|
||||
var writer = Mock.Of<CodeWriter>();
|
||||
return new Mock<ChunkVisitor<CodeWriter>>(writer, codeBuilderContext);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,17 +181,13 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
|
||||
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);
|
||||
|
||||
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 tagHelperDescriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
new TagHelperDescriptor("p", "PTagHelper", "SomeAssembly", ContentBehavior.None),
|
||||
new TagHelperDescriptor("p", "PTagHelper", "SomeAssembly"),
|
||||
new TagHelperDescriptor("input",
|
||||
"InputTagHelper",
|
||||
"SomeAssembly",
|
||||
ContentBehavior.None,
|
||||
new TagHelperAttributeDescriptor[] {
|
||||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
|
||||
}),
|
||||
new TagHelperDescriptor("input",
|
||||
"InputTagHelper2",
|
||||
"SomeAssembly",
|
||||
ContentBehavior.None,
|
||||
new TagHelperAttributeDescriptor[] {
|
||||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
|
||||
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)
|
||||
: base(context)
|
||||
|
|
@ -88,11 +86,12 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
public override void RenderAttributeValue([NotNull] TagHelperAttributeDescriptor attributeInfo,
|
||||
[NotNull] CSharpCodeWriter writer,
|
||||
[NotNull] CodeBuilderContext context,
|
||||
[NotNull] Action<CSharpCodeWriter> renderAttributeValue)
|
||||
[NotNull] Action<CSharpCodeWriter> renderAttributeValue,
|
||||
bool complexValue)
|
||||
{
|
||||
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.Diagnostics;
|
||||
using System.Linq;
|
||||
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;
|
||||
|
|
@ -78,6 +80,11 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
_tagHelperDescriptors = tagHelperDescriptors;
|
||||
}
|
||||
|
||||
protected internal override CodeBuilder CreateCodeBuilder(CodeBuilderContext context)
|
||||
{
|
||||
return Host.DecorateCodeBuilder(new TestCSharpCodeBuilder(context), context);
|
||||
}
|
||||
|
||||
protected internal override RazorParser CreateParser(string fileName)
|
||||
{
|
||||
var parser = base.CreateParser(fileName);
|
||||
|
|
@ -87,5 +94,37 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
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")));
|
||||
}
|
||||
|
||||
[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]
|
||||
public void FunctionsDirective()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
|||
var rewritten = rewritingContext.SyntaxTree;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, results.ParserErrors.Count);
|
||||
Assert.Equal(0, results.ParserErrors.Count());
|
||||
EvaluateParseTree(rewritten,
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
|
|
@ -277,7 +277,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
|||
var rewritten = rewritingContext.SyntaxTree;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, results.ParserErrors.Count);
|
||||
Assert.Equal(0, results.ParserErrors.Count());
|
||||
Assert.Equal(rewritten.Children.Count(), results.Document.Children.Count());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ namespace Microsoft.AspNet.Razor.Test.Parser
|
|||
public void VisitThrowsOnNullVisitor()
|
||||
{
|
||||
ParserVisitor target = null;
|
||||
var errorSink = new ParserErrorSink();
|
||||
var results = new ParserResults(new BlockBuilder() { Type = BlockType.Comment }.Build(),
|
||||
Enumerable.Empty<TagHelperDescriptor>(),
|
||||
parserErrors: new List<RazorError>());
|
||||
errorSink);
|
||||
|
||||
Assert.Throws<ArgumentNullException>("self", () => target.Visit(results));
|
||||
}
|
||||
|
|
@ -39,9 +40,10 @@ namespace Microsoft.AspNet.Razor.Test.Parser
|
|||
// Arrange
|
||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||
var root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
||||
var errorSink = new ParserErrorSink();
|
||||
var results = new ParserResults(root,
|
||||
Enumerable.Empty<TagHelperDescriptor>(),
|
||||
parserErrors: new List<RazorError>());
|
||||
errorSink);
|
||||
|
||||
// Act
|
||||
targetMock.Object.Visit(results);
|
||||
|
|
@ -56,11 +58,17 @@ namespace Microsoft.AspNet.Razor.Test.Parser
|
|||
// Arrange
|
||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||
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("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
|
||||
targetMock.Object.Visit(results);
|
||||
|
|
@ -76,11 +84,10 @@ namespace Microsoft.AspNet.Razor.Test.Parser
|
|||
// Arrange
|
||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||
var root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
||||
List<RazorError> errors = new List<RazorError>() {
|
||||
new RazorError("Foo", 1, 0, 1),
|
||||
new RazorError("Bar", 2, 0, 2)
|
||||
};
|
||||
var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errors);
|
||||
var errorSink = new ParserErrorSink();
|
||||
errorSink.OnError(new RazorError("Foo", 1, 0, 1));
|
||||
errorSink.OnError(new RazorError("Bar", 2, 0, 2));
|
||||
var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errorSink);
|
||||
|
||||
// Act
|
||||
targetMock.Object.Visit(results);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,8 @@ namespace Microsoft.AspNet.Razor.Test
|
|||
"different-class",
|
||||
"different-ns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: true);
|
||||
shouldGenerateLinePragmas: true,
|
||||
errorSink: new ParserErrorSink());
|
||||
|
||||
var expected = new CSharpCodeBuilder(codeBuilderContext);
|
||||
|
||||
|
|
|
|||
|
|
@ -168,8 +168,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
new ParserErrorSink());
|
||||
var document = new MarkupBlock(Factory.Markup("Hello World"));
|
||||
|
||||
// Act & Assert
|
||||
Assert.DoesNotThrow(() => addOrRemoveTagHelperSpanVisitor.GetDescriptors(document));
|
||||
// Act
|
||||
var descriptors = addOrRemoveTagHelperSpanVisitor.GetDescriptors(document);
|
||||
|
||||
Assert.Empty(descriptors);
|
||||
}
|
||||
|
||||
private class TestTagHelperDescriptorResolver : ITagHelperDescriptorResolver
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
public void TagHelperDescriptorProvider_GetTagHelpersReturnsNothingForUnregisteredTags()
|
||||
{
|
||||
// Arrange
|
||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
|
||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly", ContentBehavior.None);
|
||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
|
||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly");
|
||||
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor };
|
||||
var provider = new TagHelperDescriptorProvider(descriptors);
|
||||
|
||||
|
|
@ -29,9 +29,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
public void TagHelperDescriptorProvider_GetTagHelpersDoesNotReturnNonCatchAllTagsForCatchAll()
|
||||
{
|
||||
// Arrange
|
||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
|
||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly", ContentBehavior.None);
|
||||
var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly", ContentBehavior.None);
|
||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
|
||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly");
|
||||
var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly");
|
||||
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
|
||||
var provider = new TagHelperDescriptorProvider(descriptors);
|
||||
|
||||
|
|
@ -47,9 +47,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
public void TagHelperDescriptorProvider_GetTagHelpersReturnsCatchAllsWithEveryTagName()
|
||||
{
|
||||
// Arrange
|
||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
|
||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly", ContentBehavior.None);
|
||||
var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly", ContentBehavior.None);
|
||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
|
||||
var spanDescriptor = new TagHelperDescriptor("span", "foo2", "SomeAssembly");
|
||||
var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly");
|
||||
var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
|
||||
var provider = new TagHelperDescriptorProvider(descriptors);
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
public void TagHelperDescriptorProvider_DuplicateDescriptorsAreNotPartOfTagHelperDescriptorPool()
|
||||
{
|
||||
// Arrange
|
||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
|
||||
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
|
||||
var descriptors = new TagHelperDescriptor[] { divDescriptor, divDescriptor };
|
||||
var provider = new TagHelperDescriptorProvider(descriptors);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,430 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
{
|
||||
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
|
||||
{
|
||||
get
|
||||
|
|
@ -94,7 +518,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
// Arrange
|
||||
var descriptors = new TagHelperDescriptor[]
|
||||
{
|
||||
new TagHelperDescriptor("person", "PersonTagHelper", "personAssembly", ContentBehavior.None,
|
||||
new TagHelperDescriptor("person", "PersonTagHelper", "personAssembly",
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor("age", "Age", typeof(int).FullName),
|
||||
|
|
@ -105,9 +529,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
var providerContext = new TagHelperDescriptorProvider(descriptors);
|
||||
|
||||
// Act & Assert
|
||||
EvaluateData(providerContext,
|
||||
documentContent,
|
||||
expectedOutput,
|
||||
EvaluateData(providerContext,
|
||||
documentContent,
|
||||
expectedOutput,
|
||||
expectedErrors: Enumerable.Empty<RazorError>());
|
||||
}
|
||||
|
||||
|
|
@ -117,8 +541,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
var errorFormat = "Found a malformed '{0}' tag helper. Tag helpers must have a start and end tag or " +
|
||||
"be self closing.";
|
||||
var malformedErrorFormat = "Found a malformed '{0}' tag helper. Tag helpers must have a start and " +
|
||||
"end tag or be self closing.";
|
||||
var dateTimeNow = new MarkupBlock(
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
|
|
@ -130,16 +554,23 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
"<p class=foo dynamic=@DateTime.Now style=color:red;><strong></p></strong>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", factory.Markup("foo") },
|
||||
{ "dynamic", new MarkupBlock(dateTimeNow) },
|
||||
{ "style", factory.Markup("color:red;") }
|
||||
},
|
||||
new MarkupTagHelperBlock("strong",
|
||||
blockFactory.MarkupTagBlock("</p>")))),
|
||||
new RazorError(string.Format(CultureInfo.InvariantCulture, errorFormat, "p"),
|
||||
SourceLocation.Zero)
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", factory.Markup("foo") },
|
||||
{ "dynamic", new MarkupBlock(dateTimeNow) },
|
||||
{ "style", factory.Markup("color:red;") }
|
||||
},
|
||||
new MarkupTagHelperBlock("strong")),
|
||||
blockFactory.MarkupTagBlock("</strong>")),
|
||||
new RazorError[]
|
||||
{
|
||||
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[] {
|
||||
"<div><p>Hello <strong>World</strong></div>",
|
||||
|
|
@ -150,8 +581,12 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
new MarkupTagHelperBlock("strong",
|
||||
factory.Markup("World")),
|
||||
blockFactory.MarkupTagBlock("</div>"))),
|
||||
new RazorError(string.Format(CultureInfo.InvariantCulture, errorFormat, "p"),
|
||||
absoluteIndex: 5, lineIndex: 0, columnIndex: 5)
|
||||
new RazorError[]
|
||||
{
|
||||
new RazorError(
|
||||
string.Format(CultureInfo.InvariantCulture, malformedErrorFormat, "p"),
|
||||
absoluteIndex: 5, lineIndex: 0, columnIndex: 5)
|
||||
}
|
||||
};
|
||||
yield return new object[] {
|
||||
"<div><p>Hello <strong>World</div>",
|
||||
|
|
@ -162,8 +597,15 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
new MarkupTagHelperBlock("strong",
|
||||
factory.Markup("World"),
|
||||
blockFactory.MarkupTagBlock("</div>")))),
|
||||
new RazorError(string.Format(CultureInfo.InvariantCulture, errorFormat, "strong"),
|
||||
absoluteIndex: 14, lineIndex: 0, columnIndex: 14)
|
||||
new RazorError[]
|
||||
{
|
||||
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[] {
|
||||
"<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;") }
|
||||
},
|
||||
factory.Markup("World")))),
|
||||
new RazorError(string.Format(CultureInfo.InvariantCulture, errorFormat, "p"),
|
||||
SourceLocation.Zero)
|
||||
new RazorError[]
|
||||
{
|
||||
new RazorError(
|
||||
string.Format(CultureInfo.InvariantCulture, malformedErrorFormat, "p"),
|
||||
SourceLocation.Zero)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -191,9 +637,9 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
public void TagHelperParseTreeRewriter_CreatesErrorForIncompleteTagHelper(
|
||||
string documentContent,
|
||||
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
|
||||
|
|
@ -1268,7 +1714,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
foreach (var tagName in tagNames)
|
||||
{
|
||||
descriptors.Add(
|
||||
new TagHelperDescriptor(tagName, tagName + "taghelper", "SomeAssembly", ContentBehavior.None));
|
||||
new TagHelperDescriptor(tagName, tagName + "taghelper", "SomeAssembly"));
|
||||
}
|
||||
|
||||
return new TagHelperDescriptorProvider(descriptors);
|
||||
|
|
@ -1292,8 +1738,10 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
var rewritingContext = new RewritingContext(results.Document, errorSink);
|
||||
new TagHelperParseTreeRewriter(provider).Rewrite(rewritingContext);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ namespace TestOutput
|
|||
public class BasicTagHelpers
|
||||
{
|
||||
#line hidden
|
||||
#pragma warning disable 0414
|
||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||
#pragma warning restore 0414
|
||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||
|
|
@ -25,57 +27,117 @@ namespace TestOutput
|
|||
Instrumentation.BeginContext(27, 49, true);
|
||||
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||
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>();
|
||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
Instrumentation.BeginContext(99, 10, true);
|
||||
WriteLiteral("\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
Instrumentation.BeginContext(116, 10, true);
|
||||
WriteLiteral("\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
||||
__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.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(206, 8, true);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ namespace TestOutput
|
|||
#pragma warning disable 1998
|
||||
public override async Task ExecuteAsync()
|
||||
{
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||
__InputTagHelper.Type = "text";
|
||||
|
|
@ -42,7 +41,12 @@ namespace TestOutput
|
|||
__InputTagHelper.Type = "checkbox";
|
||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||
#line 7 "BasicTagHelpers.cshtml"
|
||||
__InputTagHelper2.Checked = true;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ namespace TestOutput
|
|||
public class BasicTagHelpers
|
||||
{
|
||||
#line hidden
|
||||
#pragma warning disable 0414
|
||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||
#pragma warning restore 0414
|
||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||
|
|
@ -26,57 +28,117 @@ namespace TestOutput
|
|||
Instrumentation.BeginContext(27, 49, true);
|
||||
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||
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>();
|
||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
Instrumentation.BeginContext(99, 10, true);
|
||||
WriteLiteral("\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
Instrumentation.BeginContext(116, 10, true);
|
||||
WriteLiteral("\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
||||
__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.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(206, 8, true);
|
||||
|
|
|
|||
|
|
@ -41,12 +41,6 @@ if (true)
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
#line 8 "ComplexTagHelpers.cshtml"
|
||||
__o = DateTime.Now;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 10 "ComplexTagHelpers.cshtml"
|
||||
|
||||
|
||||
|
|
@ -60,11 +54,11 @@ __o = DateTime.Now;
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||
__InputTagHelper.Type = "text";
|
||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
#line 13 "ComplexTagHelpers.cshtml"
|
||||
}
|
||||
else
|
||||
|
|
@ -73,7 +67,6 @@ __o = DateTime.Now;
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||
#line 16 "ComplexTagHelpers.cshtml"
|
||||
__o = checkbox;
|
||||
|
|
@ -83,7 +76,12 @@ __o = checkbox;
|
|||
__InputTagHelper.Type = string.Empty;
|
||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||
__InputTagHelper2.Checked = true;
|
||||
#line 16 "ComplexTagHelpers.cshtml"
|
||||
__InputTagHelper2.Checked = true;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||
#line 17 "ComplexTagHelpers.cshtml"
|
||||
__o = true ? "checkbox" : "anything";
|
||||
|
|
@ -121,7 +119,77 @@ if(true) {
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
#line 8 "ComplexTagHelpers.cshtml"
|
||||
__o = DateTime.Now;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||
|
|
@ -8,7 +8,9 @@ namespace TestOutput
|
|||
public class ComplexTagHelpers
|
||||
{
|
||||
#line hidden
|
||||
#pragma warning disable 0414
|
||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||
#pragma warning restore 0414
|
||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||
|
|
@ -38,23 +40,8 @@ namespace TestOutput
|
|||
Instrumentation.BeginContext(78, 55, true);
|
||||
WriteLiteral(" <div class=\"randomNonTagHelperAttribute\">\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
||||
__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());
|
||||
Instrumentation.BeginContext(171, 34, true);
|
||||
WriteLiteral("\r\n <h1>Set Time:</h1>\r\n");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||
WriteLiteral("\r\n <h1>Set Time:</h1>\r\n");
|
||||
#line 10 "ComplexTagHelpers.cshtml"
|
||||
|
||||
|
||||
|
|
@ -68,36 +55,62 @@ Write(DateTime.Now);
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(245, 16, true);
|
||||
WriteLiteral(" ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
Instrumentation.BeginContext(264, 10, true);
|
||||
WriteLiteral("New Time: ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
||||
__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.AddHtmlAttribute("value", "");
|
||||
__tagHelperExecutionContext.AddHtmlAttribute("placeholder", "Enter in a new time...");
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
Instrumentation.BeginContext(344, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
WriteLiteral(" ");
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||
WriteLiteral("New Time: ");
|
||||
__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.AddHtmlAttribute("value", "");
|
||||
__tagHelperExecutionContext.AddHtmlAttribute("placeholder", "Enter in a new time...");
|
||||
__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();
|
||||
}
|
||||
, 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"
|
||||
}
|
||||
else
|
||||
|
|
@ -106,117 +119,475 @@ Write(DateTime.Now);
|
|||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(394, 16, true);
|
||||
WriteLiteral(" ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
Instrumentation.BeginContext(413, 14, true);
|
||||
WriteLiteral("Current Time: ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||
StartWritingScope();
|
||||
WriteLiteral(" ");
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||
WriteLiteral("Current Time: ");
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
|
||||
}
|
||||
, StartWritingScope, EndWritingScope);
|
||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||
StartWritingScope();
|
||||
#line 16 "ComplexTagHelpers.cshtml"
|
||||
Write(checkbox);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||
__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();
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
Instrumentation.BeginContext(468, 18, true);
|
||||
WriteLiteral("\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||
StartWritingScope();
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
|
||||
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
|
||||
__tagHelperExecutionContext.Add(__InputTagHelper2);
|
||||
__InputTagHelper2.Type = __InputTagHelper.Type;
|
||||
#line 16 "ComplexTagHelpers.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();
|
||||
}
|
||||
, 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"
|
||||
Write(true ? "checkbox" : "anything");
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||
__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(536, 18, true);
|
||||
WriteLiteral("\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input");
|
||||
__InputTagHelper = CreateTagHelper<InputTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__InputTagHelper);
|
||||
StartWritingScope();
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||
__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);
|
||||
StartWritingScope();
|
||||
#line 18 "ComplexTagHelpers.cshtml"
|
||||
if(true) {
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
WriteLiteral(" checkbox ");
|
||||
WriteLiteral(" checkbox ");
|
||||
#line 18 "ComplexTagHelpers.cshtml"
|
||||
} else {
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
WriteLiteral(" anything ");
|
||||
WriteLiteral(" anything ");
|
||||
#line 18 "ComplexTagHelpers.cshtml"
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||
__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(637, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
|
||||
__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");
|
||||
#line 19 "ComplexTagHelpers.cshtml"
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
Instrumentation.BeginContext(654, 8, true);
|
||||
WriteLiteral(" ");
|
||||
Instrumentation.EndContext();
|
||||
WriteLiteral(" ");
|
||||
}
|
||||
, 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());
|
||||
__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");
|
||||
Instrumentation.EndContext();
|
||||
#line 22 "ComplexTagHelpers.cshtml"
|
||||
#line 35 "ComplexTagHelpers.cshtml"
|
||||
}
|
||||
|
||||
#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()
|
||||
{
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__PTagHelper.Age = 1337;
|
||||
#line 3 "SingleTagHelper.cshtml"
|
||||
__PTagHelper.Age = 1337;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ namespace TestOutput
|
|||
public class SingleTagHelper
|
||||
{
|
||||
#line hidden
|
||||
#pragma warning disable 0414
|
||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||
#pragma warning restore 0414
|
||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||
|
|
@ -24,17 +26,35 @@ namespace TestOutput
|
|||
Instrumentation.BeginContext(27, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p");
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", "test", async() => {
|
||||
WriteLiteral("Body of Tag");
|
||||
}
|
||||
, StartWritingScope, EndWritingScope);
|
||||
__PTagHelper = CreateTagHelper<PTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__PTagHelper);
|
||||
__PTagHelper.Age = 1337;
|
||||
#line 3 "SingleTagHelper.cshtml"
|
||||
__PTagHelper.Age = 1337;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__tagHelperExecutionContext.AddTagHelperAttribute("age", __PTagHelper.Age);
|
||||
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
Instrumentation.BeginContext(63, 11, true);
|
||||
WriteLiteral("Body of Tag");
|
||||
Instrumentation.EndContext();
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,40 @@ MyHelper(string val)
|
|||
Instrumentation.BeginContext(62, 19, true);
|
||||
WriteLiteralTo(__razor_helper_writer, " <div>\r\n ");
|
||||
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>();
|
||||
__tagHelperExecutionContext.Add(__MyTagHelper);
|
||||
StartWritingScope();
|
||||
|
|
@ -48,28 +81,22 @@ Write(DateTime.Now);
|
|||
__tagHelperExecutionContext.AddHtmlAttribute("unboundproperty", __tagHelperStringValueBuffer.ToString());
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
Instrumentation.BeginContext(184, 52, true);
|
||||
WriteLiteralTo(__razor_helper_writer, "\r\n In None ContentBehavior.\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("nestedtaghelper");
|
||||
__NestedTagHelper = CreateTagHelper<NestedTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
||||
StartWritingScope();
|
||||
WriteLiteral("Some buffered values with a value of ");
|
||||
#line 8 "TagHelpersInHelper.cshtml"
|
||||
Write(val);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext, __tagHelperStringValueBuffer).Result;
|
||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
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.GeneratePreContent());
|
||||
if (__tagHelperExecutionContext.Output.ContentSet)
|
||||
{
|
||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateContent());
|
||||
}
|
||||
else if (__tagHelperExecutionContext.ChildContentRetrieved)
|
||||
{
|
||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.GetChildContentAsync().Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
StartWritingScope(__razor_helper_writer);
|
||||
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
|
||||
EndWritingScope();
|
||||
}
|
||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GeneratePostContent());
|
||||
WriteLiteralTo(__razor_helper_writer, __tagHelperExecutionContext.Output.GenerateEndTag());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
Instrumentation.BeginContext(336, 14, true);
|
||||
|
|
@ -89,7 +116,9 @@ Write(DateTime.Now);
|
|||
#line hidden
|
||||
|
||||
#line hidden
|
||||
#pragma warning disable 0414
|
||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||
#pragma warning restore 0414
|
||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||
|
|
@ -106,23 +135,33 @@ Write(DateTime.Now);
|
|||
Instrumentation.BeginContext(27, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("mytaghelper");
|
||||
__MyTagHelper = CreateTagHelper<MyTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__MyTagHelper);
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
Instrumentation.BeginContext(367, 9, false);
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("mytaghelper", "test", async() => {
|
||||
#line 12 "TagHelpersInHelper.cshtml"
|
||||
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>();
|
||||
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
||||
StartWritingScope();
|
||||
WriteLiteral("Custom Value");
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext, __tagHelperStringValueBuffer).Result;
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
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());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
}
|
||||
|
|
@ -131,7 +170,26 @@ Write(MyHelper(item => new Template((__razor_template_writer) => {
|
|||
|
||||
#line default
|
||||
#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());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
Instrumentation.BeginContext(439, 2, true);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ namespace TestOutput
|
|||
public class TagHelpersInSection
|
||||
{
|
||||
#line hidden
|
||||
#pragma warning disable 0414
|
||||
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
|
||||
#pragma warning restore 0414
|
||||
private TagHelperExecutionContext __tagHelperExecutionContext = null;
|
||||
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
|
||||
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
|
||||
|
|
@ -38,7 +40,40 @@ namespace TestOutput
|
|||
Instrumentation.BeginContext(87, 21, true);
|
||||
WriteLiteralTo(__razor_template_writer, "\r\n <div>\r\n ");
|
||||
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>();
|
||||
__tagHelperExecutionContext.Add(__MyTagHelper);
|
||||
StartWritingScope();
|
||||
|
|
@ -62,28 +97,22 @@ Write(DateTime.Now);
|
|||
__tagHelperExecutionContext.AddHtmlAttribute("unboundproperty", __tagHelperStringValueBuffer.ToString());
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
|
||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
Instrumentation.BeginContext(211, 52, true);
|
||||
WriteLiteralTo(__razor_template_writer, "\r\n In None ContentBehavior.\r\n ");
|
||||
Instrumentation.EndContext();
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("nestedtaghelper");
|
||||
__NestedTagHelper = CreateTagHelper<NestedTagHelper>();
|
||||
__tagHelperExecutionContext.Add(__NestedTagHelper);
|
||||
StartWritingScope();
|
||||
WriteLiteral("Some buffered values with ");
|
||||
#line 11 "TagHelpersInSection.cshtml"
|
||||
Write(code);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
__tagHelperStringValueBuffer = EndWritingScope();
|
||||
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext, __tagHelperStringValueBuffer).Result;
|
||||
WriteLiteralTo(__razor_template_writer, __tagHelperExecutionContext.Output.GenerateStartTag());
|
||||
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.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());
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
Instrumentation.BeginContext(353, 14, true);
|
||||
|
|
|
|||
|
|
@ -18,5 +18,18 @@
|
|||
<input type='@if(true) { <text>checkbox</text> } else { <text>anything</text> }' />
|
||||
}
|
||||
</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>
|
||||
}
|
||||
|
|
@ -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",
|
||||
"Microsoft.AspNet.Razor": "4.0.0-*",
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
"Xunit.KRunner": "1.0.0-*"
|
||||
"xunit.runner.kre": "1.0.0-*"
|
||||
},
|
||||
"commands": {
|
||||
"test": "Xunit.KRunner"
|
||||
"test": "xunit.runner.kre"
|
||||
},
|
||||
"frameworks": {
|
||||
"aspnet50": { },
|
||||
"aspnetcore50": {
|
||||
"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