Skip to content

Commit 3841b96

Browse files
committed
Add custom attributes
1 parent bf30ff0 commit 3841b96

File tree

7 files changed

+65
-17
lines changed

7 files changed

+65
-17
lines changed

BlazorPreRender/BlazorApp1/BlazorApp1/Pages/Counter.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@page "/counter"
2-
@attribute [System.ComponentModel.Description("Counter")]
2+
@attribute [MenuItem("oi-plus", "Counter")]
33

44
<h1>Counter</h1>
55

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
@page "/Example"
2-
@attribute [System.ComponentModel.Description("Example")]
2+
@attribute [MenuItem("oi-list-rich", "Example")]
33

44
<h3>Example</h3>

BlazorPreRender/BlazorApp1/BlazorApp1/Pages/Index.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@page "/"
2-
@attribute [System.ComponentModel.Description("Home")]
2+
@attribute [MenuItem("oi-home", "Home", order: int.MinValue)]
33

44
<h1>Hello, world!</h1>
55

BlazorPreRender/BlazorApp1/BlazorApp1/Shared/NavMenu.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
{
1212
<li class="nav-item px-3">
1313
<NavLink class="nav-link" href="@pageDetail.Route" Match="NavLinkMatch.All">
14-
@pageDetail.Title
14+
<span class="oi @pageDetail.Icon" aria-hidden="true"></span> @pageDetail.Title
1515
</NavLink>
1616
</li>
1717
}

BlazorPreRender/BlazorApp1/SourceGenerators/PageDetailsGenerator.cs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@ namespace SourceGenerators
1515
public class PageDetailsGenerator : ISourceGenerator
1616
{
1717
private const string RouteAttributeName = "Microsoft.AspNetCore.Components.RouteAttribute";
18-
private const string DescriptionAttributeName = "System.ComponentModel.Description";
18+
private const string MenuItemAttributeName = "MenuItem";
1919

2020
public void Execute(GeneratorExecutionContext context)
2121
{
2222
try
2323
{
24-
// Debugger.Launch();
2524

2625
IEnumerable<RouteableComponent> menuComponents = GetMenuComponents(context.Compilation);
2726

2827
context.AddSource("PageDetail", SourceText.From(Templates.PageDetail(), Encoding.UTF8));
28+
context.AddSource("MenuItemAttribute", SourceText.From(Templates.MenuItemAttribute(), Encoding.UTF8));
2929
var pageDetailsSource = SourceText.From(Templates.MenuPages(menuComponents), Encoding.UTF8);
3030
context.AddSource("PageDetails", pageDetailsSource);
3131
}
@@ -47,11 +47,13 @@ private static ImmutableArray<RouteableComponent> GetMenuComponents(Compilation
4747
IEnumerable<ClassDeclarationSyntax> allClasses = allNodes
4848
.Where(d => d.IsKind(SyntaxKind.ClassDeclaration))
4949
.OfType<ClassDeclarationSyntax>();
50-
50+
5151
return allClasses
5252
.Select(component => TryGetMenuComponent(compilation, component))
5353
.Where(page => page is not null)
54-
.Cast<RouteableComponent>()// stops the nullable lies
54+
.Cast<RouteableComponent>() // stops the nullable lies
55+
.OrderBy(x => x.Order)
56+
.ThenBy(x => x.Title)
5557
.ToImmutableArray();
5658
}
5759

@@ -61,20 +63,20 @@ private static ImmutableArray<RouteableComponent> GetMenuComponents(Compilation
6163
.SelectMany(x => x.Attributes)
6264
.Where(attr =>
6365
attr.Name.ToString() == RouteAttributeName
64-
|| attr.Name.ToString() == DescriptionAttributeName)
66+
|| attr.Name.ToString() == MenuItemAttributeName)
6567
.ToList();
6668

6769
var routeAttribute = attributes.FirstOrDefault(attr => attr.Name.ToString() == RouteAttributeName);
68-
var descriptionAttribute = attributes.FirstOrDefault(attr => attr.Name.ToString() == DescriptionAttributeName);
70+
var menuItemAttribute = attributes.FirstOrDefault(attr => attr.Name.ToString() == MenuItemAttributeName);
6971

70-
if (routeAttribute is null || descriptionAttribute is null)
72+
if (routeAttribute is null || menuItemAttribute is null)
7173
{
7274
return null;
7375
}
7476

7577
if (
7678
routeAttribute.ArgumentList?.Arguments.Count != 1 ||
77-
descriptionAttribute.ArgumentList?.Arguments.Count != 1)
79+
menuItemAttribute.ArgumentList?.Arguments.Count < 2)
7880
{
7981
// no route path or description value
8082
return null;
@@ -86,11 +88,27 @@ private static ImmutableArray<RouteableComponent> GetMenuComponents(Compilation
8688
var routeExpr = routeArg.Expression;
8789
var routeTemplate = semanticModel.GetConstantValue(routeExpr).ToString();
8890

89-
var descriptionArg = descriptionAttribute.ArgumentList.Arguments[0];
91+
var iconArg = menuItemAttribute.ArgumentList.Arguments[0];
92+
var iconExpr = iconArg.Expression;
93+
var icon = semanticModel.GetConstantValue(iconExpr).ToString();
94+
95+
var descriptionArg = menuItemAttribute.ArgumentList.Arguments[1];
9096
var descriptionExpr = descriptionArg.Expression;
9197
var title = semanticModel.GetConstantValue(descriptionExpr).ToString();
9298

93-
return new RouteableComponent(routeTemplate, title);
99+
var order = 0;
100+
if (menuItemAttribute.ArgumentList?.Arguments.Count == 3)
101+
{
102+
var orderArg = menuItemAttribute.ArgumentList.Arguments[2];
103+
var orderExpr = orderArg.Expression;
104+
var maybeOrder = semanticModel.GetConstantValue(orderExpr);
105+
if (maybeOrder.HasValue)
106+
{
107+
order = (int) maybeOrder.Value;
108+
}
109+
}
110+
111+
return new RouteableComponent(routeTemplate, title, icon, order);
94112
}
95113
}
96114
}

BlazorPreRender/BlazorApp1/SourceGenerators/RouteableComponent.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ public class RouteableComponent
44
{
55
public string Route { get; }
66
public string Title { get; }
7+
public string Icon { get; }
8+
public int Order { get; }
79

8-
public RouteableComponent(string route, string title)
10+
public RouteableComponent(string route, string title, string icon, int order)
911
{
1012
Title = title;
13+
Icon = icon;
14+
Order = order;
1115
Route = route;
1216
}
1317
}

BlazorPreRender/BlazorApp1/SourceGenerators/Templates.cs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,33 @@ public static string PageDetail()
3939
return @"
4040
namespace BlazorApp1
4141
{
42-
public record PageDetail(string Route, string Title);
42+
public record PageDetail(string Route, string Title, string Icon);
43+
}
44+
";
45+
}
46+
47+
public static string MenuItemAttribute()
48+
{
49+
return @"
50+
namespace BlazorApp1
51+
{
52+
public class MenuItemAttribute : System.Attribute
53+
{
54+
public string Icon { get; }
55+
public string Description { get; }
56+
public int Order { get; }
57+
58+
public MenuItemAttribute(
59+
string icon,
60+
string description,
61+
int order = 0
62+
)
63+
{
64+
Icon = icon;
65+
Description = description;
66+
Order = order;
67+
}
68+
}
4369
}
4470
";
4571
}
@@ -62,7 +88,7 @@ public static class PageDetails
6288
");
6389
foreach (var page in pages)
6490
{
65-
sb.AppendLine($"new PageDetail(\"{page.Route}\", \"{page.Title}\"),");
91+
sb.AppendLine($"new PageDetail(\"{page.Route}\", \"{page.Title}\", \"{page.Icon}\"),");
6692
}
6793

6894
sb.Append(@"

0 commit comments

Comments
 (0)