mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
Merge pull request #234 from lightpanda-io/html-anchor
dom: add target and href accessors to anchor
This commit is contained in:
@@ -15,11 +15,17 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
const std = @import("std");
|
||||
|
||||
const parser = @import("../netsurf.zig");
|
||||
const generate = @import("../generate.zig");
|
||||
|
||||
const jsruntime = @import("jsruntime");
|
||||
const Case = jsruntime.test_utils.Case;
|
||||
const checkCases = jsruntime.test_utils.checkCases;
|
||||
|
||||
const Element = @import("../dom/element.zig").Element;
|
||||
const URL = @import("../url/url.zig").URL;
|
||||
|
||||
// HTMLElement interfaces
|
||||
pub const Interfaces = .{
|
||||
@@ -126,10 +132,270 @@ pub const HTMLUnknownElement = struct {
|
||||
pub const mem_guarantied = true;
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/#the-a-element
|
||||
pub const HTMLAnchorElement = struct {
|
||||
pub const Self = parser.Anchor;
|
||||
pub const prototype = *HTMLElement;
|
||||
pub const mem_guarantied = true;
|
||||
|
||||
pub fn get_target(self: *parser.Anchor) ![]const u8 {
|
||||
return try parser.anchorGetTarget(self);
|
||||
}
|
||||
|
||||
pub fn set_target(self: *parser.Anchor, href: []const u8) !void {
|
||||
return try parser.anchorSetTarget(self, href);
|
||||
}
|
||||
|
||||
pub fn get_download(_: *parser.Anchor) ![]const u8 {
|
||||
return ""; // TODO
|
||||
}
|
||||
|
||||
pub fn get_href(self: *parser.Anchor) ![]const u8 {
|
||||
return try parser.anchorGetHref(self);
|
||||
}
|
||||
|
||||
pub fn set_href(self: *parser.Anchor, href: []const u8) !void {
|
||||
return try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
pub fn get_hreflang(self: *parser.Anchor) ![]const u8 {
|
||||
return try parser.anchorGetHrefLang(self);
|
||||
}
|
||||
|
||||
pub fn set_hreflang(self: *parser.Anchor, href: []const u8) !void {
|
||||
return try parser.anchorSetHrefLang(self, href);
|
||||
}
|
||||
|
||||
pub fn get_type(self: *parser.Anchor) ![]const u8 {
|
||||
return try parser.anchorGetType(self);
|
||||
}
|
||||
|
||||
pub fn set_type(self: *parser.Anchor, t: []const u8) !void {
|
||||
return try parser.anchorSetType(self, t);
|
||||
}
|
||||
|
||||
pub fn get_rel(self: *parser.Anchor) ![]const u8 {
|
||||
return try parser.anchorGetRel(self);
|
||||
}
|
||||
|
||||
pub fn set_rel(self: *parser.Anchor, t: []const u8) !void {
|
||||
return try parser.anchorSetRel(self, t);
|
||||
}
|
||||
|
||||
pub fn get_text(self: *parser.Anchor) !?[]const u8 {
|
||||
return try parser.nodeTextContent(parser.anchorToNode(self));
|
||||
}
|
||||
|
||||
pub fn set_text(self: *parser.Anchor, v: []const u8) !void {
|
||||
return try parser.nodeSetTextContent(parser.anchorToNode(self), v);
|
||||
}
|
||||
|
||||
inline fn url(self: *parser.Anchor, alloc: std.mem.Allocator) !URL {
|
||||
const href = try parser.anchorGetHref(self);
|
||||
return URL.constructor(alloc, href, null); // TODO inject base url
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_origin(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try u.get_origin(alloc);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_protocol(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return u.get_protocol(alloc);
|
||||
}
|
||||
|
||||
pub fn set_protocol(self: *parser.Anchor, alloc: std.mem.Allocator, v: []const u8) !void {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
u.uri.scheme = v;
|
||||
const href = try u.format(alloc);
|
||||
defer alloc.free(href);
|
||||
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_host(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try u.get_host(alloc);
|
||||
}
|
||||
|
||||
pub fn set_host(self: *parser.Anchor, alloc: std.mem.Allocator, v: []const u8) !void {
|
||||
// search : separator
|
||||
var p: ?u16 = null;
|
||||
var h: []const u8 = undefined;
|
||||
for (v, 0..) |c, i| {
|
||||
if (c == ':') {
|
||||
h = v[0..i];
|
||||
p = try std.fmt.parseInt(u16, v[i + 1 ..], 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
if (p) |pp| {
|
||||
u.uri.host = h;
|
||||
u.uri.port = pp;
|
||||
} else {
|
||||
u.uri.host = v;
|
||||
u.uri.port = null;
|
||||
}
|
||||
|
||||
const href = try u.format(alloc);
|
||||
defer alloc.free(href);
|
||||
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_hostname(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try alloc.dupe(u8, u.get_hostname());
|
||||
}
|
||||
|
||||
pub fn set_hostname(self: *parser.Anchor, alloc: std.mem.Allocator, v: []const u8) !void {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
u.uri.host = v;
|
||||
const href = try u.format(alloc);
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_port(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try u.get_port(alloc);
|
||||
}
|
||||
|
||||
pub fn set_port(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
if (v != null and v.?.len > 0) {
|
||||
u.uri.port = try std.fmt.parseInt(u16, v.?, 10);
|
||||
} else {
|
||||
u.uri.port = null;
|
||||
}
|
||||
|
||||
const href = try u.format(alloc);
|
||||
defer alloc.free(href);
|
||||
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_username(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try alloc.dupe(u8, u.get_username());
|
||||
}
|
||||
|
||||
pub fn set_username(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
u.uri.user = v;
|
||||
const href = try u.format(alloc);
|
||||
defer alloc.free(href);
|
||||
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_password(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try alloc.dupe(u8, u.get_password());
|
||||
}
|
||||
|
||||
pub fn set_password(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
u.uri.password = v;
|
||||
const href = try u.format(alloc);
|
||||
defer alloc.free(href);
|
||||
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_pathname(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try alloc.dupe(u8, u.get_pathname());
|
||||
}
|
||||
|
||||
pub fn set_pathname(self: *parser.Anchor, alloc: std.mem.Allocator, v: []const u8) !void {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
u.uri.path = v;
|
||||
const href = try u.format(alloc);
|
||||
defer alloc.free(href);
|
||||
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_search(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try u.get_search(alloc);
|
||||
}
|
||||
|
||||
pub fn set_search(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
u.uri.query = v;
|
||||
const href = try u.format(alloc);
|
||||
defer alloc.free(href);
|
||||
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
// TODO return a disposable string
|
||||
pub fn get_hash(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
return try u.get_hash(alloc);
|
||||
}
|
||||
|
||||
pub fn set_hash(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
|
||||
var u = try url(self, alloc);
|
||||
defer u.deinit(alloc);
|
||||
|
||||
u.uri.fragment = v;
|
||||
const href = try u.format(alloc);
|
||||
defer alloc.free(href);
|
||||
|
||||
try parser.anchorSetHref(self, href);
|
||||
}
|
||||
|
||||
pub fn deinit(_: *parser.Anchor, _: std.mem.Allocator) void {}
|
||||
};
|
||||
|
||||
pub const HTMLAppletElement = struct {
|
||||
@@ -408,10 +674,120 @@ pub const HTMLQuoteElement = struct {
|
||||
pub const mem_guarantied = true;
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/#the-script-element
|
||||
pub const HTMLScriptElement = struct {
|
||||
pub const Self = parser.Script;
|
||||
pub const prototype = *HTMLElement;
|
||||
pub const mem_guarantied = true;
|
||||
|
||||
pub fn get_src(self: *parser.Script) !?[]const u8 {
|
||||
return try parser.elementGetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"src",
|
||||
) orelse "";
|
||||
}
|
||||
|
||||
pub fn set_src(self: *parser.Script, v: []const u8) !void {
|
||||
return try parser.elementSetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"src",
|
||||
v,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_type(self: *parser.Script) !?[]const u8 {
|
||||
return try parser.elementGetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"type",
|
||||
) orelse "";
|
||||
}
|
||||
|
||||
pub fn set_type(self: *parser.Script, v: []const u8) !void {
|
||||
return try parser.elementSetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"type",
|
||||
v,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_text(self: *parser.Script) !?[]const u8 {
|
||||
return try parser.elementGetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"text",
|
||||
) orelse "";
|
||||
}
|
||||
|
||||
pub fn set_text(self: *parser.Script, v: []const u8) !void {
|
||||
return try parser.elementSetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"text",
|
||||
v,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_integrity(self: *parser.Script) !?[]const u8 {
|
||||
return try parser.elementGetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"integrity",
|
||||
) orelse "";
|
||||
}
|
||||
|
||||
pub fn set_integrity(self: *parser.Script, v: []const u8) !void {
|
||||
return try parser.elementSetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"integrity",
|
||||
v,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_async(self: *parser.Script) !bool {
|
||||
_ = try parser.elementGetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"async",
|
||||
) orelse return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn set_async(self: *parser.Script, v: bool) !void {
|
||||
if (v) {
|
||||
return try parser.elementSetAttribute(parser.scriptToElt(self), "async", "");
|
||||
}
|
||||
|
||||
return try parser.elementRemoveAttribute(parser.scriptToElt(self), "async");
|
||||
}
|
||||
|
||||
pub fn get_defer(self: *parser.Script) !bool {
|
||||
_ = try parser.elementGetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"defer",
|
||||
) orelse false;
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn set_defer(self: *parser.Script, v: bool) !void {
|
||||
if (v) {
|
||||
return try parser.elementSetAttribute(parser.scriptToElt(self), "defer", "");
|
||||
}
|
||||
|
||||
return try parser.elementRemoveAttribute(parser.scriptToElt(self), "defer");
|
||||
}
|
||||
|
||||
pub fn get_noModule(self: *parser.Script) !bool {
|
||||
_ = try parser.elementGetAttribute(
|
||||
parser.scriptToElt(self),
|
||||
"nomodule",
|
||||
) orelse false;
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn set_noModule(self: *parser.Script, v: bool) !void {
|
||||
if (v) {
|
||||
return try parser.elementSetAttribute(parser.scriptToElt(self), "nomodule", "");
|
||||
}
|
||||
|
||||
return try parser.elementRemoveAttribute(parser.scriptToElt(self), "nomodule");
|
||||
}
|
||||
};
|
||||
|
||||
pub const HTMLSelectElement = struct {
|
||||
@@ -589,3 +965,82 @@ pub fn toInterface(comptime T: type, e: *parser.Element) !T {
|
||||
.undef => .{ .HTMLUnknownElement = @as(*parser.Unknown, @ptrCast(elem)) },
|
||||
};
|
||||
}
|
||||
|
||||
// Tests
|
||||
// -----
|
||||
|
||||
pub fn testExecFn(
|
||||
_: std.mem.Allocator,
|
||||
js_env: *jsruntime.Env,
|
||||
) anyerror!void {
|
||||
var anchor = [_]Case{
|
||||
.{ .src = "let a = document.getElementById('link')", .ex = "undefined" },
|
||||
.{ .src = "a.target", .ex = "" },
|
||||
.{ .src = "a.target = '_blank'", .ex = "_blank" },
|
||||
.{ .src = "a.target", .ex = "_blank" },
|
||||
.{ .src = "a.target = ''", .ex = "" },
|
||||
|
||||
.{ .src = "a.href", .ex = "foo" },
|
||||
.{ .src = "a.href = 'https://lightpanda.io/'", .ex = "https://lightpanda.io/" },
|
||||
.{ .src = "a.href", .ex = "https://lightpanda.io/" },
|
||||
|
||||
.{ .src = "a.origin", .ex = "https://lightpanda.io" },
|
||||
|
||||
.{ .src = "a.host = 'lightpanda.io:443'", .ex = "lightpanda.io:443" },
|
||||
.{ .src = "a.host", .ex = "lightpanda.io:443" },
|
||||
.{ .src = "a.port", .ex = "443" },
|
||||
.{ .src = "a.hostname", .ex = "lightpanda.io" },
|
||||
|
||||
.{ .src = "a.host = 'lightpanda.io'", .ex = "lightpanda.io" },
|
||||
.{ .src = "a.host", .ex = "lightpanda.io" },
|
||||
.{ .src = "a.port", .ex = "" },
|
||||
.{ .src = "a.hostname", .ex = "lightpanda.io" },
|
||||
|
||||
.{ .src = "a.host", .ex = "lightpanda.io" },
|
||||
.{ .src = "a.hostname", .ex = "lightpanda.io" },
|
||||
.{ .src = "a.hostname = 'foo.bar'", .ex = "foo.bar" },
|
||||
.{ .src = "a.href", .ex = "https://foo.bar/" },
|
||||
|
||||
.{ .src = "a.search", .ex = "" },
|
||||
.{ .src = "a.search = 'q=bar'", .ex = "q=bar" },
|
||||
.{ .src = "a.search", .ex = "?q=bar" },
|
||||
.{ .src = "a.href", .ex = "https://foo.bar/?q=bar" },
|
||||
|
||||
.{ .src = "a.hash", .ex = "" },
|
||||
.{ .src = "a.hash = 'frag'", .ex = "frag" },
|
||||
.{ .src = "a.hash", .ex = "#frag" },
|
||||
.{ .src = "a.href", .ex = "https://foo.bar/?q=bar#frag" },
|
||||
|
||||
.{ .src = "a.port", .ex = "" },
|
||||
.{ .src = "a.port = '443'", .ex = "443" },
|
||||
.{ .src = "a.host", .ex = "foo.bar:443" },
|
||||
.{ .src = "a.hostname", .ex = "foo.bar" },
|
||||
.{ .src = "a.href", .ex = "https://foo.bar:443/?q=bar#frag" },
|
||||
.{ .src = "a.port = null", .ex = "null" },
|
||||
.{ .src = "a.href", .ex = "https://foo.bar/?q=bar#frag" },
|
||||
|
||||
.{ .src = "a.href = 'foo'", .ex = "foo" },
|
||||
|
||||
.{ .src = "a.type", .ex = "" },
|
||||
.{ .src = "a.type = 'text/html'", .ex = "text/html" },
|
||||
.{ .src = "a.type", .ex = "text/html" },
|
||||
.{ .src = "a.type = ''", .ex = "" },
|
||||
|
||||
.{ .src = "a.text", .ex = "OK" },
|
||||
.{ .src = "a.text = 'foo'", .ex = "foo" },
|
||||
.{ .src = "a.text", .ex = "foo" },
|
||||
.{ .src = "a.text = 'OK'", .ex = "OK" },
|
||||
};
|
||||
try checkCases(js_env, &anchor);
|
||||
|
||||
var script = [_]Case{
|
||||
.{ .src = "let script = document.createElement('script')", .ex = "undefined" },
|
||||
.{ .src = "script.src = 'foo.bar'", .ex = "foo.bar" },
|
||||
|
||||
.{ .src = "script.async = true", .ex = "true" },
|
||||
.{ .src = "script.async", .ex = "true" },
|
||||
.{ .src = "script.async = false", .ex = "false" },
|
||||
.{ .src = "script.async", .ex = "false" },
|
||||
};
|
||||
try checkCases(js_env, &script);
|
||||
}
|
||||
|
||||
@@ -1513,6 +1513,85 @@ pub fn elementHTMLGetTagType(elem_html: *ElementHTML) !Tag {
|
||||
return @as(Tag, @enumFromInt(tag_type));
|
||||
}
|
||||
|
||||
// HTMLScriptElement
|
||||
|
||||
// scriptToElt is an helper to convert an script to an element.
|
||||
pub inline fn scriptToElt(s: *Script) *Element {
|
||||
return @as(*Element, @ptrCast(s));
|
||||
}
|
||||
|
||||
// HTMLAnchorElement
|
||||
|
||||
// anchorToNode is an helper to convert an anchor to a node.
|
||||
pub inline fn anchorToNode(a: *Anchor) *Node {
|
||||
return @as(*Node, @ptrCast(a));
|
||||
}
|
||||
|
||||
pub fn anchorGetTarget(a: *Anchor) ![]const u8 {
|
||||
var res: ?*String = undefined;
|
||||
const err = c.dom_html_anchor_element_get_target(a, &res);
|
||||
try DOMErr(err);
|
||||
if (res == null) return "";
|
||||
return strToData(res.?);
|
||||
}
|
||||
|
||||
pub fn anchorSetTarget(a: *Anchor, target: []const u8) !void {
|
||||
const err = c.dom_html_anchor_element_set_target(a, try strFromData(target));
|
||||
try DOMErr(err);
|
||||
}
|
||||
|
||||
pub fn anchorGetHref(a: *Anchor) ![]const u8 {
|
||||
var res: ?*String = undefined;
|
||||
const err = c.dom_html_anchor_element_get_href(a, &res);
|
||||
try DOMErr(err);
|
||||
if (res == null) return "";
|
||||
return strToData(res.?);
|
||||
}
|
||||
|
||||
pub fn anchorSetHref(a: *Anchor, href: []const u8) !void {
|
||||
const err = c.dom_html_anchor_element_set_href(a, try strFromData(href));
|
||||
try DOMErr(err);
|
||||
}
|
||||
|
||||
pub fn anchorGetHrefLang(a: *Anchor) ![]const u8 {
|
||||
var res: ?*String = undefined;
|
||||
const err = c.dom_html_anchor_element_get_hreflang(a, &res);
|
||||
try DOMErr(err);
|
||||
if (res == null) return "";
|
||||
return strToData(res.?);
|
||||
}
|
||||
|
||||
pub fn anchorSetHrefLang(a: *Anchor, href: []const u8) !void {
|
||||
const err = c.dom_html_anchor_element_set_hreflang(a, try strFromData(href));
|
||||
try DOMErr(err);
|
||||
}
|
||||
|
||||
pub fn anchorGetType(a: *Anchor) ![]const u8 {
|
||||
var res: ?*String = undefined;
|
||||
const err = c.dom_html_anchor_element_get_type(a, &res);
|
||||
try DOMErr(err);
|
||||
if (res == null) return "";
|
||||
return strToData(res.?);
|
||||
}
|
||||
|
||||
pub fn anchorSetType(a: *Anchor, t: []const u8) !void {
|
||||
const err = c.dom_html_anchor_element_set_type(a, try strFromData(t));
|
||||
try DOMErr(err);
|
||||
}
|
||||
|
||||
pub fn anchorGetRel(a: *Anchor) ![]const u8 {
|
||||
var res: ?*String = undefined;
|
||||
const err = c.dom_html_anchor_element_get_rel(a, &res);
|
||||
try DOMErr(err);
|
||||
if (res == null) return "";
|
||||
return strToData(res.?);
|
||||
}
|
||||
|
||||
pub fn anchorSetRel(a: *Anchor, rel: []const u8) !void {
|
||||
const err = c.dom_html_anchor_element_set_rel(a, try strFromData(rel));
|
||||
try DOMErr(err);
|
||||
}
|
||||
|
||||
// ElementsHTML
|
||||
|
||||
pub const MediaElement = struct { base: *c.dom_html_element };
|
||||
|
||||
@@ -51,6 +51,7 @@ const XHRTestExecFn = xhr.testExecFn;
|
||||
const ProgressEventTestExecFn = @import("xhr/progress_event.zig").testExecFn;
|
||||
const StorageTestExecFn = storage.testExecFn;
|
||||
const URLTestExecFn = url.testExecFn;
|
||||
const HTMLElementTestExecFn = @import("html/elements.zig").testExecFn;
|
||||
|
||||
pub const Types = jsruntime.reflect(apiweb.Interfaces);
|
||||
|
||||
@@ -117,6 +118,7 @@ fn testsAllExecFn(
|
||||
ProcessingInstructionTestExecFn,
|
||||
StorageTestExecFn,
|
||||
URLTestExecFn,
|
||||
HTMLElementTestExecFn,
|
||||
};
|
||||
|
||||
inline for (testFns) |testFn| {
|
||||
|
||||
@@ -67,17 +67,35 @@ pub const URL = struct {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *URL, alloc: std.mem.Allocator) void {
|
||||
self.search_params.deinit();
|
||||
self.search_params.deinit(alloc);
|
||||
alloc.free(self.rawuri);
|
||||
}
|
||||
|
||||
// the caller must free the returned string.
|
||||
// TODO return a disposable string
|
||||
// https://github.com/lightpanda-io/jsruntime-lib/issues/195
|
||||
pub fn get_href(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
|
||||
pub fn get_origin(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var buf = std.ArrayList(u8).init(alloc);
|
||||
defer buf.deinit();
|
||||
|
||||
try self.uri.writeToStream(.{
|
||||
.scheme = true,
|
||||
.authentication = false,
|
||||
.authority = true,
|
||||
.path = false,
|
||||
.query = false,
|
||||
.fragment = false,
|
||||
}, buf.writer());
|
||||
return try buf.toOwnedSlice();
|
||||
}
|
||||
|
||||
// get_href returns the URL by writing all its components.
|
||||
// The query is replaced by a dump of search params.
|
||||
//
|
||||
// the caller must free the returned string.
|
||||
// TODO return a disposable string
|
||||
// https://github.com/lightpanda-io/jsruntime-lib/issues/195
|
||||
pub fn get_href(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
|
||||
// retrieve the query search from search_params.
|
||||
const cur = self.uri.query;
|
||||
defer self.uri.query = cur;
|
||||
@@ -86,13 +104,21 @@ pub const URL = struct {
|
||||
try self.search_params.values.encode(q.writer());
|
||||
self.uri.query = q.items;
|
||||
|
||||
return try self.format(alloc);
|
||||
}
|
||||
|
||||
// format the url with all its components.
|
||||
pub fn format(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var buf = std.ArrayList(u8).init(alloc);
|
||||
defer buf.deinit();
|
||||
|
||||
try self.uri.writeToStream(.{
|
||||
.scheme = true,
|
||||
.authentication = true,
|
||||
.authority = true,
|
||||
.path = true,
|
||||
.query = true,
|
||||
.fragment = true,
|
||||
.path = self.uri.path.len > 0,
|
||||
.query = self.uri.query != null and self.uri.query.?.len > 0,
|
||||
.fragment = self.uri.fragment != null and self.uri.fragment.?.len > 0,
|
||||
}, buf.writer());
|
||||
return try buf.toOwnedSlice();
|
||||
}
|
||||
@@ -112,8 +138,22 @@ pub const URL = struct {
|
||||
return self.uri.password orelse "";
|
||||
}
|
||||
|
||||
pub fn get_host(self: *URL) []const u8 {
|
||||
return self.uri.host orelse "";
|
||||
// the caller must free the returned string.
|
||||
// TODO return a disposable string
|
||||
// https://github.com/lightpanda-io/jsruntime-lib/issues/195
|
||||
pub fn get_host(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
|
||||
var buf = std.ArrayList(u8).init(alloc);
|
||||
defer buf.deinit();
|
||||
|
||||
try self.uri.writeToStream(.{
|
||||
.scheme = false,
|
||||
.authentication = false,
|
||||
.authority = true,
|
||||
.path = false,
|
||||
.query = false,
|
||||
.fragment = false,
|
||||
}, buf.writer());
|
||||
return try buf.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn get_hostname(self: *URL) []const u8 {
|
||||
@@ -223,6 +263,7 @@ pub fn testExecFn(
|
||||
) anyerror!void {
|
||||
var url = [_]Case{
|
||||
.{ .src = "var url = new URL('https://foo.bar/path?query#fragment')", .ex = "undefined" },
|
||||
.{ .src = "url.origin", .ex = "https://foo.bar" },
|
||||
.{ .src = "url.href", .ex = "https://foo.bar/path?query#fragment" },
|
||||
.{ .src = "url.protocol", .ex = "https:" },
|
||||
.{ .src = "url.username", .ex = "" },
|
||||
|
||||
Reference in New Issue
Block a user