mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-15 15:58:57 +00:00
add hash support to URL stitch
This commit is contained in:
@@ -44,17 +44,12 @@ pub const Location = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_hash(_: *const Location, hash: []const u8, page: *Page) !void {
|
pub fn set_hash(_: *const Location, hash: []const u8, page: *Page) !void {
|
||||||
const current_url = page.url.raw;
|
const normalized_hash = if (hash[0] == '#')
|
||||||
|
hash
|
||||||
const base_without_hash = if (std.mem.indexOfScalar(u8, current_url, '#')) |pos|
|
|
||||||
current_url[0..pos]
|
|
||||||
else
|
else
|
||||||
current_url;
|
try std.fmt.allocPrint(page.arena, "#{s}", .{hash});
|
||||||
|
|
||||||
const normalized_hash = std.mem.trimStart(u8, hash, "#");
|
return page.navigateFromWebAPI(normalized_hash, .{ .reason = .script }, .replace);
|
||||||
const new_url = try std.fmt.allocPrint(page.arena, "{s}#{s}", .{ base_without_hash, normalized_hash });
|
|
||||||
|
|
||||||
return page.navigateFromWebAPI(new_url, .{ .reason = .script }, .replace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_protocol(self: *Location) []const u8 {
|
pub fn get_protocol(self: *Location) []const u8 {
|
||||||
|
|||||||
@@ -228,7 +228,9 @@ pub fn navigate(
|
|||||||
const committed = try page.js.createPromiseResolver(.page);
|
const committed = try page.js.createPromiseResolver(.page);
|
||||||
const finished = try page.js.createPromiseResolver(.page);
|
const finished = try page.js.createPromiseResolver(.page);
|
||||||
|
|
||||||
const new_url = try URL.parse(url, null);
|
const new_url_string = try URL.stitch(arena, url, page.url.raw, .{});
|
||||||
|
const new_url = try URL.parse(new_url_string, null);
|
||||||
|
|
||||||
const is_same_document = try page.url.eqlDocument(&new_url, arena);
|
const is_same_document = try page.url.eqlDocument(&new_url, arena);
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|||||||
@@ -1084,7 +1084,6 @@ pub const Page = struct {
|
|||||||
if (try self.url.eqlDocument(&new_url, session.transfer_arena)) {
|
if (try self.url.eqlDocument(&new_url, session.transfer_arena)) {
|
||||||
self.url = new_url;
|
self.url = new_url;
|
||||||
try self.window.changeLocation(self.url.raw, self);
|
try self.window.changeLocation(self.url.raw, self);
|
||||||
|
|
||||||
try session.navigation.updateEntries(stitched_url, kind, self, true);
|
try session.navigation.updateEntries(stitched_url, kind, self, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
58
src/url.zig
58
src/url.zig
@@ -82,17 +82,35 @@ pub const URL = struct {
|
|||||||
pub fn stitch(
|
pub fn stitch(
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
raw_path: []const u8,
|
raw_path: []const u8,
|
||||||
base: []const u8,
|
raw_base: []const u8,
|
||||||
comptime opts: StitchOpts,
|
comptime opts: StitchOpts,
|
||||||
) !StitchReturn(opts) {
|
) !StitchReturn(opts) {
|
||||||
const path = std.mem.trim(u8, raw_path, &.{ '\n', '\r' });
|
const trimmed_path = std.mem.trim(u8, raw_path, &.{ '\n', '\r' });
|
||||||
|
|
||||||
if (base.len == 0 or isCompleteHTTPUrl(path)) {
|
if (raw_base.len == 0 or isCompleteHTTPUrl(trimmed_path)) {
|
||||||
return simpleStitch(allocator, path, opts);
|
return simpleStitch(allocator, trimmed_path, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (trimmed_path.len == 0) {
|
||||||
|
return simpleStitch(allocator, raw_base, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// base should get stripped of its hash whenever we are stitching.
|
||||||
|
const base = if (std.mem.indexOfScalar(u8, raw_base, '#')) |hash_pos|
|
||||||
|
raw_base[0..hash_pos]
|
||||||
|
else
|
||||||
|
raw_base;
|
||||||
|
|
||||||
|
const path_hash_start = std.mem.indexOfScalar(u8, trimmed_path, '#');
|
||||||
|
const path = if (path_hash_start) |pos| trimmed_path[0..pos] else trimmed_path;
|
||||||
|
const hash = if (path_hash_start) |pos| trimmed_path[pos..] else "";
|
||||||
|
|
||||||
|
// if path is just hash, we just append it to base.
|
||||||
if (path.len == 0) {
|
if (path.len == 0) {
|
||||||
return simpleStitch(allocator, base, opts);
|
if (comptime opts.null_terminated) {
|
||||||
|
return std.fmt.allocPrintSentinel(allocator, "{s}{s}", .{ base, hash }, 0);
|
||||||
|
}
|
||||||
|
return std.fmt.allocPrint(allocator, "{s}{s}", .{ base, hash });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std.mem.startsWith(u8, path, "//")) {
|
if (std.mem.startsWith(u8, path, "//")) {
|
||||||
@@ -103,9 +121,9 @@ pub const URL = struct {
|
|||||||
|
|
||||||
const protocol = base[0..index];
|
const protocol = base[0..index];
|
||||||
if (comptime opts.null_terminated) {
|
if (comptime opts.null_terminated) {
|
||||||
return std.fmt.allocPrintSentinel(allocator, "{s}:{s}", .{ protocol, path }, 0);
|
return std.fmt.allocPrintSentinel(allocator, "{s}:{s}{s}", .{ protocol, path, hash }, 0);
|
||||||
}
|
}
|
||||||
return std.fmt.allocPrint(allocator, "{s}:{s}", .{ protocol, path });
|
return std.fmt.allocPrint(allocator, "{s}:{s}{s}", .{ protocol, path, hash });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quick hack because domains have to be at least 3 characters.
|
// Quick hack because domains have to be at least 3 characters.
|
||||||
@@ -126,25 +144,28 @@ pub const URL = struct {
|
|||||||
return std.fmt.allocPrint(allocator, "{s}{s}", .{ root, path });
|
return std.fmt.allocPrint(allocator, "{s}{s}", .{ root, path });
|
||||||
}
|
}
|
||||||
|
|
||||||
var old_path = std.mem.trimStart(u8, base[root.len..], "/");
|
var oldraw_path = std.mem.trimStart(u8, base[root.len..], "/");
|
||||||
if (std.mem.lastIndexOfScalar(u8, old_path, '/')) |pos| {
|
if (std.mem.lastIndexOfScalar(u8, oldraw_path, '/')) |pos| {
|
||||||
old_path = old_path[0..pos];
|
oldraw_path = oldraw_path[0..pos];
|
||||||
} else {
|
} else {
|
||||||
old_path = "";
|
oldraw_path = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// We preallocate all of the space possibly needed.
|
// We preallocate all of the space possibly needed.
|
||||||
// This is the root, old_path, new path, 3 slashes and perhaps a null terminated slot.
|
// This is the root, oldraw_path, new path, 3 slashes and perhaps a null terminated slot.
|
||||||
var out = try allocator.alloc(u8, root.len + old_path.len + path.len + 3 + if (comptime opts.null_terminated) 1 else 0);
|
var out = try allocator.alloc(
|
||||||
|
u8,
|
||||||
|
root.len + oldraw_path.len + path.len + hash.len + 3 + if (comptime opts.null_terminated) 1 else 0,
|
||||||
|
);
|
||||||
var end: usize = 0;
|
var end: usize = 0;
|
||||||
@memmove(out[0..root.len], root);
|
@memmove(out[0..root.len], root);
|
||||||
end += root.len;
|
end += root.len;
|
||||||
out[root.len] = '/';
|
out[root.len] = '/';
|
||||||
end += 1;
|
end += 1;
|
||||||
// If we don't have an old path, do nothing here.
|
// If we don't have an old path, do nothing here.
|
||||||
if (old_path.len > 0) {
|
if (oldraw_path.len > 0) {
|
||||||
@memmove(out[end .. end + old_path.len], old_path);
|
@memmove(out[end .. end + oldraw_path.len], oldraw_path);
|
||||||
end += old_path.len;
|
end += oldraw_path.len;
|
||||||
out[end] = '/';
|
out[end] = '/';
|
||||||
end += 1;
|
end += 1;
|
||||||
}
|
}
|
||||||
@@ -182,6 +203,11 @@ pub const URL = struct {
|
|||||||
read += 1;
|
read += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hash.len > 0) {
|
||||||
|
@memmove(out[write .. write + hash.len], hash);
|
||||||
|
write += hash.len;
|
||||||
|
}
|
||||||
|
|
||||||
if (comptime opts.null_terminated) {
|
if (comptime opts.null_terminated) {
|
||||||
// we always have an extra space
|
// we always have an extra space
|
||||||
out[write] = 0;
|
out[write] = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user