XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using AngleSharp.Dom;
using Jint.Native.Object;

namespace XFESystem.Browser;

public sealed partial class DomBridge
{
    private void InstallHyperlink(ObjectInstance wrapper, IElement element)
    {
        foreach (string part in new[] { "protocol", "host", "hostname", "port", "pathname", "search", "hash", "username", "password" })
            Property(wrapper, part, () => HyperlinkPart(element, part), value => SetHyperlinkPart(element, part, LimitedText(value)));
        Property(wrapper, "origin", () => HyperlinkPart(element, "origin"));
        Function(wrapper, "toString", _ => ResolveUrl(element.GetAttribute("href")));
    }
    private Uri? HyperlinkUri(IElement element) => Uri.TryCreate(ResolveUrl(element.GetAttribute("href")), UriKind.Absolute, out var uri) ? uri : null;
    private string HyperlinkPart(IElement element, string part)
    {
        var uri = HyperlinkUri(element);
        if (uri is null) return part == "origin" ? "null" : part == "protocol" ? ":" : "";
        int colon = uri.UserInfo.IndexOf(':');
        return part switch
        {
            "protocol" => uri.Scheme + ":", "host" => uri.Authority[(uri.Authority.LastIndexOf('@') + 1)..], "hostname" => uri.Host,
            "port" => uri.IsDefaultPort ? "" : uri.Port.ToString(System.Globalization.CultureInfo.InvariantCulture),
            "pathname" => uri.AbsolutePath, "search" => uri.Query, "hash" => uri.Fragment,
            "username" => colon < 0 ? uri.UserInfo : uri.UserInfo[..colon], "password" => colon < 0 ? "" : uri.UserInfo[(colon + 1)..],
            "origin" => uri.Scheme is "http" or "https" or "ftp" ? uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.UriEscaped) : "null", _ => ""
        };
    }
    private void SetHyperlinkPart(IElement element, string part, string value)
    {
        var uri = HyperlinkUri(element); if (uri is null) return;
        string next;
        try
        {
            var builder = new UriBuilder(uri);
            switch (part)
            {
                case "protocol": builder.Scheme = value.TrimEnd(':'); break;
                case "host":
                    if (!Uri.TryCreate(uri.Scheme + "://" + value + "/", UriKind.Absolute, out var authority) || authority.UserInfo.Length != 0 || authority.AbsolutePath != "/") return;
                    builder.Host = authority.Host;
                    if (!authority.IsDefaultPort || value.EndsWith(":" + authority.Port, StringComparison.Ordinal)) builder.Port = authority.Port;
                    break;
                case "hostname": builder.Host = value; break;
                case "port":
                    if (value.Length == 0) builder.Port = -1;
                    else if (int.TryParse(value, out int port) && port is >= 0 and <= 65535) builder.Port = port;
                    else return;
                    break;
                case "pathname": builder.Path = value; break;
                case "search": builder.Query = value.StartsWith('?') ? value[1..] : value; break;
                case "hash": builder.Fragment = value.StartsWith('#') ? value[1..] : value; break;
                case "username": builder.UserName = value; break;
                case "password": builder.Password = value; break;
            }
            next = builder.Uri.AbsoluteUri;
        }
        catch (Exception error) when (error is ArgumentException or FormatException) { return; }
        SetAttribute(element, "href", next);
    }
}