Files
sbox-public/engine/Sandbox.Engine/Systems/UI/Razor/RouteAttribute.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

108 lines
2.5 KiB
C#

using Sandbox;
namespace Microsoft.AspNetCore.Components;
public class RouteAttribute : System.Attribute
{
/// <summary>
/// The full url of this route (ie "/home/section/page")
/// </summary>
public string Url { get; }
/// <summary>
/// The url split into parts (ie "home" "section" "page" )
/// </summary>
public string[] Parts { get; }
public RouteAttribute( string url )
{
Url = url;
Parts = Url.Split( '/', StringSplitOptions.RemoveEmptyEntries );
}
/// <summary>
/// Given a URL, check out TypeLibrary and find a valid target
/// </summary>
public static (TypeDescription Type, RouteAttribute Attribute)? FindValidTarget( string url, string parentUrl )
{
//Log.Info( $"FindValidTarget [{url}] [{parentUrl}]" );
var val = Game.TypeLibrary.GetTypesWithAttribute<RouteAttribute>()
.Where( x => x.Attribute.IsUrl( url ) && !x.Attribute.IsUrl( parentUrl ) )
.OrderByDescending( x => x.Attribute.Url.Count( c => c == '*' ) )
.FirstOrDefault();
//Log.Info( $"Found [{val.Attribute?.Url}] [{val.Type}]" );
if ( val.Type == null )
return null;
return val;
}
bool TestPart( string part, string ours )
{
// this is a variable
if ( ours != null && ours.StartsWith( '{' ) && ours.EndsWith( '}' ) )
return true;
return part == ours;
}
/// <summary>
/// True if this matches the passed in url.
/// Queries are trimmed and ignored <c>( ?query=fff )</c>
/// Variables are tested (but not type matched or anything)
/// </summary>
public bool IsUrl( string url )
{
if ( string.IsNullOrEmpty( url ) ) return false;
if ( url.Contains( '?' ) )
{
url = url[..url.IndexOf( '?' )];
}
var a = url.Split( '/', StringSplitOptions.RemoveEmptyEntries );
for ( int i = 0; i < Parts.Length || i < a.Length; i++ )
{
var left = i < a.Length ? a[i] : null;
var right = i < Parts.Length ? Parts[i] : null;
if ( right == "*" )
return true;
if ( !TestPart( left, right ) )
return false;
}
return true;
}
/// <summary>
/// Given a Url, check for {properties} and convert them to key values
/// </summary>
public IEnumerable<(string key, string value)> ExtractProperties( string url )
{
var a = url.Split( '/', StringSplitOptions.RemoveEmptyEntries );
for ( int i = 0; i < Parts.Length; i++ )
{
if ( !Parts[i].StartsWith( '{' ) ) continue;
if ( !Parts[i].EndsWith( '}' ) ) continue;
var key = Parts[i][1..^1].Trim( '?' );
if ( i < a.Length )
{
yield return (key, a[i]);
}
else
{
yield return (key, null);
}
}
}
}