Add experimental flag to un-special-case data-
This change allows blazor to opt into treating data- attributes the same way as normal attributes in the parser.
This commit is contained in:
parent
d1c0ab587c
commit
4cd24a2b08
|
|
@ -931,7 +931,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
// First, determine if this is a 'data-' attribute (since those can't use conditional attributes)
|
||||
var name = string.Concat(nameSymbols.Select(s => s.Content));
|
||||
var attributeCanBeConditional = !name.StartsWith("data-", StringComparison.OrdinalIgnoreCase);
|
||||
var attributeCanBeConditional =
|
||||
Context.FeatureFlags.EXPERIMENTAL_AllowConditionalDataDashAttributes ||
|
||||
!name.StartsWith("data-", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
// Accept the whitespace and name
|
||||
Accept(whitespace);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
Source = new SeekableTextReader(chars, source.FilePath);
|
||||
DesignTimeMode = options.DesignTime;
|
||||
FeatureFlags = options.FeatureFlags;
|
||||
ParseLeadingDirectives = options.ParseLeadingDirectives;
|
||||
Builder = new SyntaxTreeBuilder();
|
||||
ErrorSink = new ErrorSink();
|
||||
|
|
@ -33,6 +34,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
public ErrorSink ErrorSink { get; set; }
|
||||
|
||||
public RazorParserFeatureFlags FeatureFlags { get; }
|
||||
|
||||
public HashSet<string> SeenDirectives { get; }
|
||||
|
||||
public ITextDocument Source { get; }
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
{
|
||||
var allowMinimizedBooleanTagHelperAttributes = false;
|
||||
var allowHtmlCommentsInTagHelpers = false;
|
||||
var experimental_AllowConditionalDataDashAttributes = false;
|
||||
|
||||
if (version.CompareTo(RazorLanguageVersion.Version_2_1) >= 0)
|
||||
{
|
||||
|
|
@ -17,24 +18,40 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
allowHtmlCommentsInTagHelpers = true;
|
||||
}
|
||||
|
||||
return new DefaultRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes, allowHtmlCommentsInTagHelpers);
|
||||
if (version.CompareTo(RazorLanguageVersion.Experimental) >= 0)
|
||||
{
|
||||
experimental_AllowConditionalDataDashAttributes = true;
|
||||
}
|
||||
|
||||
return new DefaultRazorParserFeatureFlags(
|
||||
allowMinimizedBooleanTagHelperAttributes,
|
||||
allowHtmlCommentsInTagHelpers,
|
||||
experimental_AllowConditionalDataDashAttributes);
|
||||
}
|
||||
|
||||
public abstract bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||
|
||||
public abstract bool AllowHtmlCommentsInTagHelpers { get; }
|
||||
|
||||
public abstract bool EXPERIMENTAL_AllowConditionalDataDashAttributes { get; }
|
||||
|
||||
private class DefaultRazorParserFeatureFlags : RazorParserFeatureFlags
|
||||
{
|
||||
public DefaultRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes, bool allowHtmlCommentsInTagHelpers)
|
||||
public DefaultRazorParserFeatureFlags(
|
||||
bool allowMinimizedBooleanTagHelperAttributes,
|
||||
bool allowHtmlCommentsInTagHelpers,
|
||||
bool experimental_AllowConditionalDataDashAttributes)
|
||||
{
|
||||
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
||||
AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelpers;
|
||||
EXPERIMENTAL_AllowConditionalDataDashAttributes = experimental_AllowConditionalDataDashAttributes;
|
||||
}
|
||||
|
||||
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||
|
||||
public override bool AllowHtmlCommentsInTagHelpers { get; }
|
||||
|
||||
public override bool EXPERIMENTAL_AllowConditionalDataDashAttributes { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1957,7 +1957,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Block expected,
|
||||
params RazorDiagnostic[] expectedErrors)
|
||||
{
|
||||
var result = ParseCodeBlock(document, descriptors, designTime: false);
|
||||
var result = ParseCodeBlock(RazorLanguageVersion.Latest, document, descriptors, designTime: false);
|
||||
|
||||
EvaluateResults(result, expected, expectedErrors);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
internal abstract ISet<string> KeywordSet { get; }
|
||||
|
||||
internal override RazorSyntaxTree ParseBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime)
|
||||
internal override RazorSyntaxTree ParseBlock(
|
||||
RazorLanguageVersion version,
|
||||
string document,
|
||||
IEnumerable<DirectiveDescriptor> directives,
|
||||
bool designTime)
|
||||
{
|
||||
return ParseCodeBlock(document, directives, designTime);
|
||||
return ParseCodeBlock(version, document, directives, designTime);
|
||||
}
|
||||
|
||||
internal void ImplicitExpressionTest(string input, params RazorDiagnostic[] errors)
|
||||
|
|
|
|||
|
|
@ -559,6 +559,30 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Assert.Equal(rewritten.Children.Count(), results.Root.Children.Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionalAttributesAreEnabledForDataAttributesWithExperimentalFlag()
|
||||
{
|
||||
ParseBlockTest(
|
||||
RazorLanguageVersion.Experimental,
|
||||
"<span data-foo='@foo'></span>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("<span"),
|
||||
new MarkupBlock(
|
||||
new AttributeBlockChunkGenerator("data-foo", new LocationTagged<string>(" data-foo='", 5, 0, 5), new LocationTagged<string>("'", 20, 0, 20)),
|
||||
Factory.Markup(" data-foo='").With(SpanChunkGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockChunkGenerator(new LocationTagged<string>(string.Empty, 16, 0, 16), 16, 0, 16),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharactersInternal.NonWhiteSpace))),
|
||||
Factory.Markup("'").With(SpanChunkGenerator.Null)),
|
||||
Factory.Markup(">").Accepts(AcceptedCharactersInternal.None)),
|
||||
new MarkupTagBlock(
|
||||
Factory.Markup("</span>").Accepts(AcceptedCharactersInternal.None))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionalAttributesAreDisabledForDataAttributesInBlock()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
{
|
||||
public abstract class MarkupParserTestBase : CodeParserTestBase
|
||||
{
|
||||
internal override RazorSyntaxTree ParseBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime)
|
||||
internal override RazorSyntaxTree ParseBlock(
|
||||
RazorLanguageVersion version,
|
||||
string document,
|
||||
IEnumerable<DirectiveDescriptor> directives,
|
||||
bool designTime)
|
||||
{
|
||||
return ParseHtmlBlock(document, directives, designTime);
|
||||
return ParseHtmlBlock(version, document, directives, designTime);
|
||||
}
|
||||
|
||||
internal virtual void SingleSpanDocumentTest(string document, BlockKindInternal blockKind, SpanKindInternal spanType)
|
||||
|
|
|
|||
|
|
@ -3962,7 +3962,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.Build(),
|
||||
};
|
||||
|
||||
var featureFlags = new TestRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes: false, allowHtmlCommentsInTagHelper: false);
|
||||
var featureFlags = new TestRazorParserFeatureFlags();
|
||||
|
||||
var expectedOutput = new MarkupBlock(
|
||||
new MarkupTagHelperBlock(
|
||||
|
|
@ -3994,15 +3994,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
private class TestRazorParserFeatureFlags : RazorParserFeatureFlags
|
||||
{
|
||||
public TestRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes, bool allowHtmlCommentsInTagHelper)
|
||||
public TestRazorParserFeatureFlags(
|
||||
bool allowMinimizedBooleanTagHelperAttributes = false,
|
||||
bool allowHtmlCommentsInTagHelper = false,
|
||||
bool experimental_AllowConditionalDataDashAttributes = false)
|
||||
{
|
||||
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
||||
AllowHtmlCommentsInTagHelpers = allowHtmlCommentsInTagHelper;
|
||||
EXPERIMENTAL_AllowConditionalDataDashAttributes = experimental_AllowConditionalDataDashAttributes;
|
||||
}
|
||||
|
||||
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||
|
||||
public override bool AllowHtmlCommentsInTagHelpers { get; }
|
||||
|
||||
public override bool EXPERIMENTAL_AllowConditionalDataDashAttributes { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,23 +32,43 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
internal RazorSyntaxTree ParseBlock(string document, bool designTime)
|
||||
{
|
||||
return ParseBlock(document, null, designTime);
|
||||
return ParseBlock(RazorLanguageVersion.Latest, document, designTime);
|
||||
}
|
||||
|
||||
internal abstract RazorSyntaxTree ParseBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime);
|
||||
|
||||
internal virtual RazorSyntaxTree ParseDocument(string document, bool designTime = false)
|
||||
internal RazorSyntaxTree ParseBlock(RazorLanguageVersion version, string document, bool designTime)
|
||||
{
|
||||
return ParseDocument(document, null, designTime);
|
||||
return ParseBlock(version, document, null, designTime);
|
||||
}
|
||||
|
||||
internal virtual RazorSyntaxTree ParseDocument(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
|
||||
internal RazorSyntaxTree ParseBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime)
|
||||
{
|
||||
return ParseBlock(RazorLanguageVersion.Latest, document, directives, designTime);
|
||||
}
|
||||
|
||||
internal abstract RazorSyntaxTree ParseBlock(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, bool designTime);
|
||||
|
||||
internal RazorSyntaxTree ParseDocument(string document, bool designTime = false)
|
||||
{
|
||||
return ParseDocument(RazorLanguageVersion.Latest, document, designTime);
|
||||
}
|
||||
|
||||
internal RazorSyntaxTree ParseDocument(RazorLanguageVersion version, string document, bool designTime = false)
|
||||
{
|
||||
return ParseDocument(version, document, null, designTime);
|
||||
}
|
||||
|
||||
internal RazorSyntaxTree ParseDocument(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
|
||||
{
|
||||
return ParseDocument(RazorLanguageVersion.Latest, document, directives, designTime);
|
||||
}
|
||||
|
||||
internal virtual RazorSyntaxTree ParseDocument(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
|
||||
{
|
||||
directives = directives ?? Array.Empty<DirectiveDescriptor>();
|
||||
|
||||
var source = TestRazorSourceDocument.Create(document, filePath: null);
|
||||
|
||||
var options = CreateParserOptions(directives, designTime);
|
||||
var options = CreateParserOptions(version, directives, designTime);
|
||||
var context = new ParserContext(source, options);
|
||||
|
||||
var codeParser = new CSharpCodeParser(directives, context);
|
||||
|
|
@ -73,12 +93,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return syntaxTree;
|
||||
}
|
||||
|
||||
internal virtual RazorSyntaxTree ParseHtmlBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
|
||||
internal virtual RazorSyntaxTree ParseHtmlBlock(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
|
||||
{
|
||||
directives = directives ?? Array.Empty<DirectiveDescriptor>();
|
||||
|
||||
var source = TestRazorSourceDocument.Create(document, filePath: null);
|
||||
var options = CreateParserOptions(directives, designTime);
|
||||
var options = CreateParserOptions(version, directives, designTime);
|
||||
var context = new ParserContext(source, options);
|
||||
|
||||
var parser = new HtmlMarkupParser(context);
|
||||
|
|
@ -95,12 +115,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return RazorSyntaxTree.Create(root, source, diagnostics, options);
|
||||
}
|
||||
|
||||
internal virtual RazorSyntaxTree ParseCodeBlock(string document, bool designTime = false)
|
||||
internal RazorSyntaxTree ParseCodeBlock(string document, bool designTime = false)
|
||||
{
|
||||
return ParseCodeBlock(document, Enumerable.Empty<DirectiveDescriptor>(), designTime);
|
||||
return ParseCodeBlock(RazorLanguageVersion.Latest, document, Enumerable.Empty<DirectiveDescriptor>(), designTime);
|
||||
}
|
||||
|
||||
internal virtual RazorSyntaxTree ParseCodeBlock(
|
||||
RazorLanguageVersion version,
|
||||
string document,
|
||||
IEnumerable<DirectiveDescriptor> directives,
|
||||
bool designTime)
|
||||
|
|
@ -108,7 +129,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
directives = directives ?? Array.Empty<DirectiveDescriptor>();
|
||||
|
||||
var source = TestRazorSourceDocument.Create(document, filePath: null);
|
||||
var options = CreateParserOptions(directives, designTime);
|
||||
var options = CreateParserOptions(version, directives, designTime);
|
||||
var context = new ParserContext(source, options);
|
||||
|
||||
var parser = new CSharpCodeParser(directives, context);
|
||||
|
|
@ -152,6 +173,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
ParseBlockTest(document, null, designTime, expectedErrors);
|
||||
}
|
||||
|
||||
internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, Block expectedRoot)
|
||||
{
|
||||
ParseBlockTest(version, document, expectedRoot, false, null);
|
||||
}
|
||||
|
||||
internal virtual void ParseBlockTest(string document, Block expectedRoot)
|
||||
{
|
||||
ParseBlockTest(document, expectedRoot, false, null);
|
||||
|
|
@ -182,9 +208,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
ParseBlockTest(document, null, expected, designTime, expectedErrors);
|
||||
}
|
||||
|
||||
internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, Block expected, bool designTime, params RazorDiagnostic[] expectedErrors)
|
||||
{
|
||||
ParseBlockTest(version, document, null, expected, designTime, expectedErrors);
|
||||
}
|
||||
|
||||
internal virtual void ParseBlockTest(string document, IEnumerable<DirectiveDescriptor> directives, Block expected, bool designTime, params RazorDiagnostic[] expectedErrors)
|
||||
{
|
||||
var result = ParseBlock(document, directives, designTime);
|
||||
ParseBlockTest(RazorLanguageVersion.Latest, document, directives, expected, designTime, expectedErrors);
|
||||
}
|
||||
|
||||
internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, Block expected, bool designTime, params RazorDiagnostic[] expectedErrors)
|
||||
{
|
||||
var result = ParseBlock(version, document, directives, designTime);
|
||||
|
||||
if (FixupSpans)
|
||||
{
|
||||
|
|
@ -604,24 +640,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return block.Build();
|
||||
}
|
||||
|
||||
private static RazorParserOptions CreateParserOptions(IEnumerable<DirectiveDescriptor> directives, bool designTime)
|
||||
private static RazorParserOptions CreateParserOptions(
|
||||
RazorLanguageVersion version,
|
||||
IEnumerable<DirectiveDescriptor> directives,
|
||||
bool designTime)
|
||||
{
|
||||
if (designTime)
|
||||
{
|
||||
return RazorParserOptions.CreateDesignTime(ConfigureOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RazorParserOptions.Create(ConfigureOptions);
|
||||
}
|
||||
|
||||
void ConfigureOptions(RazorParserOptionsBuilder builder)
|
||||
{
|
||||
foreach (var directive in directives)
|
||||
{
|
||||
builder.Directives.Add(directive);
|
||||
}
|
||||
}
|
||||
return new DefaultRazorParserOptions(
|
||||
directives.ToArray(),
|
||||
designTime,
|
||||
parseLeadingDirectives: false,
|
||||
version: version);
|
||||
}
|
||||
|
||||
private class IgnoreOutputBlock : Block
|
||||
|
|
|
|||
Loading…
Reference in New Issue