Skip to content

Commit 6b42b5a

Browse files
committed
anchor: implement HTMLHyperlinkElementUtils interface
https://html.spec.whatwg.org/#htmlhyperlinkelementutils
1 parent e12d6e8 commit 6b42b5a

File tree

2 files changed

+216
-8
lines changed

2 files changed

+216
-8
lines changed

src/html/elements.zig

Lines changed: 186 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,182 @@ pub const HTMLAnchorElement = struct {
195195
return URL.constructor(alloc, href, null); // TODO inject base url
196196
}
197197

198+
// TODO return a disposable string
199+
pub fn get_origin(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
200+
var u = try url(self, alloc);
201+
defer u.deinit(alloc);
202+
203+
return try u.get_origin(alloc);
204+
}
205+
206+
// TODO return a disposable string
207+
pub fn get_protocol(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
208+
var u = try url(self, alloc);
209+
defer u.deinit(alloc);
210+
211+
return u.get_protocol(alloc);
212+
}
213+
214+
pub fn set_protocol(self: *parser.Anchor, alloc: std.mem.Allocator, v: []const u8) !void {
215+
var u = try url(self, alloc);
216+
defer u.deinit(alloc);
217+
218+
u.uri.scheme = v;
219+
const href = try u.format(alloc);
220+
defer alloc.free(href);
221+
222+
try parser.anchorSetHref(self, href);
223+
}
224+
198225
// TODO return a disposable string
199226
pub fn get_host(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
200227
var u = try url(self, alloc);
201228
defer u.deinit(alloc);
202229

203-
return try alloc.dupe(u8, u.get_host());
230+
return try u.get_host(alloc);
204231
}
205232

206233
pub fn set_host(self: *parser.Anchor, alloc: std.mem.Allocator, v: []const u8) !void {
234+
_ = self;
235+
_ = alloc;
236+
_ = v;
237+
// TODO
238+
return error.NotImplemented;
239+
}
240+
241+
// TODO return a disposable string
242+
pub fn get_hostname(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
243+
var u = try url(self, alloc);
244+
defer u.deinit(alloc);
245+
246+
return try alloc.dupe(u8, u.get_hostname());
247+
}
248+
249+
pub fn set_hostname(self: *parser.Anchor, alloc: std.mem.Allocator, v: []const u8) !void {
207250
var u = try url(self, alloc);
208251
defer u.deinit(alloc);
209252

210253
u.uri.host = v;
211-
const href = try u.get_href(alloc);
254+
const href = try u.format(alloc);
255+
try parser.anchorSetHref(self, href);
256+
}
257+
258+
// TODO return a disposable string
259+
pub fn get_port(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
260+
var u = try url(self, alloc);
261+
defer u.deinit(alloc);
262+
263+
return try u.get_port(alloc);
264+
}
265+
266+
pub fn set_port(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
267+
var u = try url(self, alloc);
268+
defer u.deinit(alloc);
269+
270+
if (v != null and v.?.len > 0) {
271+
u.uri.port = try std.fmt.parseInt(u16, v.?, 10);
272+
} else {
273+
u.uri.port = null;
274+
}
275+
276+
const href = try u.format(alloc);
277+
defer alloc.free(href);
278+
279+
try parser.anchorSetHref(self, href);
280+
}
281+
282+
// TODO return a disposable string
283+
pub fn get_username(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
284+
var u = try url(self, alloc);
285+
defer u.deinit(alloc);
286+
287+
return try alloc.dupe(u8, u.get_username());
288+
}
289+
290+
pub fn set_username(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
291+
var u = try url(self, alloc);
292+
defer u.deinit(alloc);
293+
294+
u.uri.user = v;
295+
const href = try u.format(alloc);
296+
defer alloc.free(href);
297+
298+
try parser.anchorSetHref(self, href);
299+
}
300+
301+
// TODO return a disposable string
302+
pub fn get_password(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
303+
var u = try url(self, alloc);
304+
defer u.deinit(alloc);
305+
306+
return try alloc.dupe(u8, u.get_password());
307+
}
308+
309+
pub fn set_password(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
310+
var u = try url(self, alloc);
311+
defer u.deinit(alloc);
312+
313+
u.uri.password = v;
314+
const href = try u.format(alloc);
315+
defer alloc.free(href);
316+
317+
try parser.anchorSetHref(self, href);
318+
}
319+
320+
// TODO return a disposable string
321+
pub fn get_pathname(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
322+
var u = try url(self, alloc);
323+
defer u.deinit(alloc);
324+
325+
return try alloc.dupe(u8, u.get_pathname());
326+
}
327+
328+
pub fn set_pathname(self: *parser.Anchor, alloc: std.mem.Allocator, v: []const u8) !void {
329+
var u = try url(self, alloc);
330+
defer u.deinit(alloc);
331+
332+
u.uri.path = v;
333+
const href = try u.format(alloc);
334+
defer alloc.free(href);
335+
336+
try parser.anchorSetHref(self, href);
337+
}
338+
339+
// TODO return a disposable string
340+
pub fn get_search(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
341+
var u = try url(self, alloc);
342+
defer u.deinit(alloc);
343+
344+
return try u.get_search(alloc);
345+
}
346+
347+
pub fn set_search(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
348+
var u = try url(self, alloc);
349+
defer u.deinit(alloc);
350+
351+
u.uri.query = v;
352+
const href = try u.format(alloc);
353+
defer alloc.free(href);
354+
355+
try parser.anchorSetHref(self, href);
356+
}
357+
358+
// TODO return a disposable string
359+
pub fn get_hash(self: *parser.Anchor, alloc: std.mem.Allocator) ![]const u8 {
360+
var u = try url(self, alloc);
361+
defer u.deinit(alloc);
362+
363+
return try u.get_hash(alloc);
364+
}
365+
366+
pub fn set_hash(self: *parser.Anchor, alloc: std.mem.Allocator, v: ?[]const u8) !void {
367+
var u = try url(self, alloc);
368+
defer u.deinit(alloc);
369+
370+
u.uri.fragment = v;
371+
const href = try u.format(alloc);
372+
defer alloc.free(href);
373+
212374
try parser.anchorSetHref(self, href);
213375
}
214376

@@ -691,10 +853,31 @@ pub fn testExecFn(
691853
.{ .src = "a.href = 'https://lightpanda.io/'", .ex = "https://lightpanda.io/" },
692854
.{ .src = "a.href", .ex = "https://lightpanda.io/" },
693855

856+
.{ .src = "a.origin", .ex = "https://lightpanda.io" },
857+
694858
.{ .src = "a.host", .ex = "lightpanda.io" },
695-
.{ .src = "a.host = 'foo.bar'", .ex = "foo.bar" },
859+
.{ .src = "a.hostname", .ex = "lightpanda.io" },
860+
.{ .src = "a.hostname = 'foo.bar'", .ex = "foo.bar" },
696861
.{ .src = "a.href", .ex = "https://foo.bar/" },
697862

863+
.{ .src = "a.search", .ex = "" },
864+
.{ .src = "a.search = 'q=bar'", .ex = "q=bar" },
865+
.{ .src = "a.search", .ex = "?q=bar" },
866+
.{ .src = "a.href", .ex = "https://foo.bar/?q=bar" },
867+
868+
.{ .src = "a.hash", .ex = "" },
869+
.{ .src = "a.hash = 'frag'", .ex = "frag" },
870+
.{ .src = "a.hash", .ex = "#frag" },
871+
.{ .src = "a.href", .ex = "https://foo.bar/?q=bar#frag" },
872+
873+
.{ .src = "a.port", .ex = "" },
874+
.{ .src = "a.port = '443'", .ex = "443" },
875+
.{ .src = "a.host", .ex = "foo.bar:443" },
876+
.{ .src = "a.hostname", .ex = "foo.bar" },
877+
.{ .src = "a.href", .ex = "https://foo.bar:443/?q=bar#frag" },
878+
.{ .src = "a.port = null", .ex = "null" },
879+
.{ .src = "a.href", .ex = "https://foo.bar/?q=bar#frag" },
880+
698881
.{ .src = "a.href = 'foo'", .ex = "foo" },
699882

700883
.{ .src = "a.type", .ex = "" },

src/url/url.zig

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ pub const URL = struct {
7171
alloc.free(self.rawuri);
7272
}
7373

74+
// the caller must free the returned string.
75+
// TODO return a disposable string
76+
// https://github.com/lightpanda-io/jsruntime-lib/issues/195
7477
pub fn get_origin(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
7578
var buf = std.ArrayList(u8).init(alloc);
7679
defer buf.deinit();
@@ -86,13 +89,13 @@ pub const URL = struct {
8689
return try buf.toOwnedSlice();
8790
}
8891

92+
// get_href returns the URL by writing all its components.
93+
// The query is replaced by a dump of search params.
94+
//
8995
// the caller must free the returned string.
9096
// TODO return a disposable string
9197
// https://github.com/lightpanda-io/jsruntime-lib/issues/195
9298
pub fn get_href(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
93-
var buf = std.ArrayList(u8).init(alloc);
94-
defer buf.deinit();
95-
9699
// retrieve the query search from search_params.
97100
const cur = self.uri.query;
98101
defer self.uri.query = cur;
@@ -101,6 +104,14 @@ pub const URL = struct {
101104
try self.search_params.values.encode(q.writer());
102105
self.uri.query = q.items;
103106

107+
return try self.format(alloc);
108+
}
109+
110+
// format the url with all its components.
111+
pub fn format(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
112+
var buf = std.ArrayList(u8).init(alloc);
113+
defer buf.deinit();
114+
104115
try self.uri.writeToStream(.{
105116
.scheme = true,
106117
.authentication = true,
@@ -127,8 +138,22 @@ pub const URL = struct {
127138
return self.uri.password orelse "";
128139
}
129140

130-
pub fn get_host(self: *URL) []const u8 {
131-
return self.uri.host orelse "";
141+
// the caller must free the returned string.
142+
// TODO return a disposable string
143+
// https://github.com/lightpanda-io/jsruntime-lib/issues/195
144+
pub fn get_host(self: *URL, alloc: std.mem.Allocator) ![]const u8 {
145+
var buf = std.ArrayList(u8).init(alloc);
146+
defer buf.deinit();
147+
148+
try self.uri.writeToStream(.{
149+
.scheme = false,
150+
.authentication = false,
151+
.authority = true,
152+
.path = false,
153+
.query = false,
154+
.fragment = false,
155+
}, buf.writer());
156+
return try buf.toOwnedSlice();
132157
}
133158

134159
pub fn get_hostname(self: *URL) []const u8 {

0 commit comments

Comments
 (0)