authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-22 16:38:34 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-22 16:38:34 -08:00
log3ea94ec9e260de535cc778c297f33c100d918465
treea2643089db86558b44c1f6bc596d18e5d82e4695
parent9392e9e3186ef5f84d2a37432a0116fbd96a803d

populate username field


3 files changed, 32 insertions(+), 18 deletions(-)

generate.ts+1-1
...@@ -50,7 +50,7 @@ pub fn parsePass(input: []const u8, base: ?[]const u8, href: []const u8, origin:...@@ -50,7 +50,7 @@ pub fn parsePass(input: []const u8, base: ?[]const u8, href: []const u8, origin:
50 _ = href;50 _ = href;
51 _ = origin;51 _ = origin;
52 try expect(u.protocol).toEqualString(protocol);52 try expect(u.protocol).toEqualString(protocol);
53 _ = username;53 try expect(u.username).toEqualString(username);
54 _ = password;54 _ = password;
55 _ = host;55 _ = host;
56 _ = hostname;56 _ = hostname;
url.zig+30-16
...@@ -8,6 +8,7 @@ pub const URL = struct {...@@ -8,6 +8,7 @@ pub const URL = struct {
8 href: []const u8,8 href: []const u8,
9 scheme: []const u8 = "",9 scheme: []const u8 = "",
10 protocol: []const u8,10 protocol: []const u8,
11 username: []const u8,
1112
12 pub const HostKind = enum {13 pub const HostKind = enum {
13 name,14 name,
...@@ -327,11 +328,21 @@ pub const URL = struct {...@@ -327,11 +328,21 @@ pub const URL = struct {
327 // 3. Set atSignSeen to true.328 // 3. Set atSignSeen to true.
328 atSignSeen = true;329 atSignSeen = true;
329 // 4. For each codePoint in buffer:330 // 4. For each codePoint in buffer:
330 {331 var it = std.unicode.Utf8View.initUnchecked(buffer.items).iterator();
332 while (it.nextCodepointSlice()) |sl| {
331 // 1. If codePoint is U+003A (:) and passwordTokenSeen is false, then set passwordTokenSeen to true and continue.333 // 1. If codePoint is U+003A (:) and passwordTokenSeen is false, then set passwordTokenSeen to true and continue.
334 if (sl[0] == ':' and !passwordTokenSeen) {
335 passwordTokenSeen = true;
336 continue;
337 }
332 // 2. Let encodedCodePoints be the result of running UTF-8 percent-encode codePoint using the userinfo percent-encode set.338 // 2. Let encodedCodePoints be the result of running UTF-8 percent-encode codePoint using the userinfo percent-encode set.
333 // 3. If passwordTokenSeen is true, then append encodedCodePoints to url’s password.339 // 3. If passwordTokenSeen is true, then append encodedCodePoints to url’s password.
334 // 4. Otherwise, append encodedCodePoints to url’s username.340 // 4. Otherwise, append encodedCodePoints to url’s username.
341 if (passwordTokenSeen) {
342 try percentEncodeScalarML(&href, 5, sl, is_userinfo_percent_char);
343 } else {
344 try percentEncodeScalarML(&href, 3, sl, is_userinfo_percent_char);
345 }
335 }346 }
336 // 5. Set buffer to the empty string.347 // 5. Set buffer to the empty string.
337 buffer.clearRetainingCapacity();348 buffer.clearRetainingCapacity();
...@@ -769,6 +780,7 @@ pub const URL = struct {...@@ -769,6 +780,7 @@ pub const URL = struct {
769 const url: URL = .{780 const url: URL = .{
770 .href = _href,781 .href = _href,
771 .protocol = _href[0..extras.sum(usize, href.lengths[0..2])],782 .protocol = _href[0..extras.sum(usize, href.lengths[0..2])],
783 .username = _href[extras.sum(usize, href.lengths[0..2])..][0..href.lengths[3]],
772 };784 };
773 return url;785 return url;
774 }786 }
...@@ -1323,23 +1335,25 @@ fn is_fragment_percent_char(c: u8) bool {...@@ -1323,23 +1335,25 @@ fn is_fragment_percent_char(c: u8) bool {
1323 if (c == '`') return true;1335 if (c == '`') return true;
1324 return is_c0control_percent_char(c);1336 return is_c0control_percent_char(c);
1325}1337}
13261338/// https://url.spec.whatwg.org/#userinfo-percent-encode-set
1327// fn is_userinfo_percent_char(c: u8) bool {1339fn is_userinfo_percent_char(c: u8) bool {
1328// if (c == '/') return true;1340 if (c == '/') return true;
1329// if (c == ':') return true;1341 if (c == ':') return true;
1330// if (c == ';') return true;1342 if (c == ';') return true;
1331// if (c == '=') return true;1343 if (c == '=') return true;
1332// if (c == '@') return true;1344 if (c == '@') return true;
1333// if (c >= '[' and c <= '^') return true;1345 if (c >= '[' and c <= '^') return true;
1334// if (c == '|') return true;1346 if (c == '|') return true;
1335// return is_path_percent_char(c);1347 return is_path_percent_char(c);
1336// }1348}
1349// /// https://url.spec.whatwg.org/#component-percent-encode-set
1337// fn is_component_percent_char(c: u8) bool {1350// fn is_component_percent_char(c: u8) bool {
1338// if (c >= '$' and c <= '&') return true;1351// if (c >= '$' and c <= '&') return true;
1339// if (c == '+') return true;1352// if (c == '+') return true;
1340// if (c == ',') return true;1353// if (c == ',') return true;
1341// return is_userinfo_percent_char(c);1354// return is_userinfo_percent_char(c);
1342// }1355// }
1356// /// https://url.spec.whatwg.org/#application-x-www-form-urlencoded-percent-encode-set
1343// fn is_formurlencoded_percent_char(c: u8) bool {1357// fn is_formurlencoded_percent_char(c: u8) bool {
1344// if (c == '!') return true;1358// if (c == '!') return true;
1345// if (c >= '\'' and c <= ')') return true;1359// if (c >= '\'' and c <= ')') return true;
...@@ -1360,7 +1374,7 @@ fn percentEncodeScalarAL(list: *std.ArrayList(u8), cp: []const u8, comptime set:...@@ -1360,7 +1374,7 @@ fn percentEncodeScalarAL(list: *std.ArrayList(u8), cp: []const u8, comptime set:
1360 if (set(cp[0])) {1374 if (set(cp[0])) {
1361 for (cp) |b| {1375 for (cp) |b| {
1362 try list.append('%');1376 try list.append('%');
1363 try list.writer().print("{d:0<2}", .{b});1377 try list.writer().print("{X:0<2}", .{b});
1364 }1378 }
1365 } else {1379 } else {
1366 try list.append(cp[0]);1380 try list.append(cp[0]);
...@@ -1372,7 +1386,7 @@ fn percentEncodeAL(list: *std.ArrayList(u8), input: []const u8, comptime set: fn...@@ -1372,7 +1386,7 @@ fn percentEncodeAL(list: *std.ArrayList(u8), input: []const u8, comptime set: fn
1372 if (set(sl[0])) {1386 if (set(sl[0])) {
1373 for (sl) |b| {1387 for (sl) |b| {
1374 try list.append('%');1388 try list.append('%');
1375 try list.writer().print("{d:0<2}", .{b});1389 try list.writer().print("{X:0<2}", .{b});
1376 }1390 }
1377 } else {1391 } else {
1378 try list.appendSlice(sl);1392 try list.appendSlice(sl);
...@@ -1383,7 +1397,7 @@ fn percentEncodeScalarML(list: *ManyArrayList(15, u8), n: usize, cp: []const u8,...@@ -1383,7 +1397,7 @@ fn percentEncodeScalarML(list: *ManyArrayList(15, u8), n: usize, cp: []const u8,
1383 if (set(cp[0])) {1397 if (set(cp[0])) {
1384 for (cp) |b| {1398 for (cp) |b| {
1385 try list.appendSlice(n, &.{'%'});1399 try list.appendSlice(n, &.{'%'});
1386 try list.print(n, "{d:0<2}", .{b});1400 try list.print(n, "{X:0<2}", .{b});
1387 }1401 }
1388 } else {1402 } else {
1389 try list.appendSlice(n, &.{cp[0]});1403 try list.appendSlice(n, &.{cp[0]});
...@@ -1395,7 +1409,7 @@ fn percentEncodeML(list: *ManyArrayList(15, u8), n: usize, input: []const u8, co...@@ -1395,7 +1409,7 @@ fn percentEncodeML(list: *ManyArrayList(15, u8), n: usize, input: []const u8, co
1395 if (set(sl[0])) {1409 if (set(sl[0])) {
1396 for (sl) |b| {1410 for (sl) |b| {
1397 try list.appendSlice(n, &.{'%'});1411 try list.appendSlice(n, &.{'%'});
1398 try list.print(n, "{d:0<2}", .{b});1412 try list.print(n, "{X:0<2}", .{b});
1399 }1413 }
1400 } else {1414 } else {
1401 try list.appendSlice(n, sl);1415 try list.appendSlice(n, sl);
zig-out/test.zig+1-1
...@@ -20,7 +20,7 @@ pub fn parsePass(input: []const u8, base: ?[]const u8, href: []const u8, origin:...@@ -20,7 +20,7 @@ pub fn parsePass(input: []const u8, base: ?[]const u8, href: []const u8, origin:
20 _ = href;20 _ = href;
21 _ = origin;21 _ = origin;
22 try expect(u.protocol).toEqualString(protocol);22 try expect(u.protocol).toEqualString(protocol);
23 _ = username;23 try expect(u.username).toEqualString(username);
24 _ = password;24 _ = password;
25 _ = host;25 _ = host;
26 _ = hostname;26 _ = hostname;