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);
}
}
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);
}
}