Browse Source

Merge pull request #4213 from AvaloniaUI/fixes/3552-dash-class-name

Allow dash in style class identifiers.
pull/4221/head
Dariusz Komosiński 6 years ago
committed by GitHub
parent
commit
74bca9f7ac
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 45
      src/Avalonia.Base/Utilities/StyleClassParser.cs
  2. 5
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  3. 4
      src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
  4. 54
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs

45
src/Avalonia.Base/Utilities/StyleClassParser.cs

@ -0,0 +1,45 @@
using System;
using System.Globalization;
namespace Avalonia.Utilities
{
#if !BUILDTASK
public
#endif
static class StyleClassParser
{
public static ReadOnlySpan<char> ParseStyleClass(this ref CharacterReader r)
{
if (IsValidIdentifierStart(r.Peek))
{
return r.TakeWhile(c => IsValidIdentifierChar(c));
}
else
{
return ReadOnlySpan<char>.Empty;
}
}
private static bool IsValidIdentifierStart(char c)
{
return char.IsLetter(c) || c == '_';
}
private static bool IsValidIdentifierChar(char c)
{
if (IsValidIdentifierStart(c) || c == '-')
{
return true;
}
else
{
var cat = CharUnicodeInfo.GetUnicodeCategory(c);
return cat == UnicodeCategory.NonSpacingMark ||
cat == UnicodeCategory.SpacingCombiningMark ||
cat == UnicodeCategory.ConnectorPunctuation ||
cat == UnicodeCategory.Format ||
cat == UnicodeCategory.DecimalDigitNumber;
}
}
}
}

5
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -42,7 +42,10 @@
<Compile Include="../Avalonia.Base/Utilities/IdentifierParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="../Avalonia.Base/Utilities/StyleClassParser.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Remove="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\**\obj\**\*.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml/XamlIl\xamlil.github\src\XamlIl\TypeSystem\SreTypeSystem.cs" />
<PackageReference Include="Avalonia.Unofficial.Cecil" Version="20190417.2.0" PrivateAssets="All" />

4
src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs

@ -154,7 +154,7 @@ namespace Avalonia.Markup.Parsers
private static (State, ISyntax) ParseColon(ref CharacterReader r)
{
var identifier = r.ParseIdentifier();
var identifier = r.ParseStyleClass();
if (identifier.IsEmpty)
{
@ -214,7 +214,7 @@ namespace Avalonia.Markup.Parsers
private static (State, ISyntax) ParseClass(ref CharacterReader r)
{
var @class = r.ParseIdentifier();
var @class = r.ParseStyleClass();
if (@class.IsEmpty)
{
throw new ExpressionParseException(r.Position, $"Expected a class name after '.'.");

54
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs

@ -382,5 +382,59 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.Equal(Border.WidthProperty, border.Transitions[0].Property);
}
}
[Fact]
public void Style_Can_Use_Class_Selector_With_Dash()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Window.Styles>
<Style Selector='Border.foo-bar'>
<Setter Property='Background' Value='Red'/>
</Style>
</Window.Styles>
<StackPanel>
<Border Name='foo' Classes='foo-bar'/>
</StackPanel>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var foo = window.FindControl<Border>("foo");
Assert.Equal(Colors.Red, ((ISolidColorBrush)foo.Background).Color);
}
}
[Fact]
public void Style_Can_Use_Pseudolass_Selector_With_Dash()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Window.Styles>
<Style Selector='Border:foo-bar'>
<Setter Property='Background' Value='Red'/>
</Style>
</Window.Styles>
<StackPanel>
<Border Name='foo'/>
</StackPanel>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var foo = window.FindControl<Border>("foo");
Assert.Null(foo.Background);
((IPseudoClasses)foo.Classes).Add(":foo-bar");
Assert.Equal(Colors.Red, ((ISolidColorBrush)foo.Background).Color);
}
}
}
}

Loading…
Cancel
Save