╭──────────╮ │← previous│ ╰──────────╯ ╭ added ──────────────╮ │src/ui/Home/About.zig│ ╰─────────────────────╯ ╭ changed ───────────────╮ │src/ui/Repo/Markdown.zig│ ╰────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │12 const RichText = ui.widget.RichText; │ │13 │ │14 // a rendered markdown file: one child per block, word-wrapped to the width. │ │15 +// without `data` (a file outside any repo), repo-relative links aren't clickable.│ │16 pub const View = struct { │ │17 box: wgt.Box(ui.Widget), │ │18 // where focus rests off the links, covering the whole document; it's │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │19 // registered after the links so they win hit-testing │ │20 body: *Focus, │ │21 │ │21 - pub fn init(allocator: std.mem.Allocator, doc: md.Document, data: *const Files, file_path: []const u8, page_arena: *std.heap.ArenaAllocator) !View { │ │22 + pub fn init(allocator: std.mem.Allocator, doc: md.Document, data: ?*const Files, file_path: []const u8, page_arena: *std.heap.ArenaAllocator) !View {│ │23 const builder: Builder = .{ │ │24 .allocator = allocator, │ │25 .data = data, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │128 // turns blocks into widgets, resolving links against the viewed file. │ │129 const Builder = struct { │ │130 allocator: std.mem.Allocator, │ │130 - data: *const Files, │ │131 + data: ?*const Files, │ │132 // the viewed file's directory, which relative links resolve against│ │133 dir: []const u8, │ │134 page_arena: *std.heap.ArenaAllocator, │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │220 if (std.ascii.startsWithIgnoreCase(dest, scheme)) return std.fmt.allocPrint(aa, "{s}{s}", .{ ui.raw_link_prefix, dest });│ │221 } │ │222 if (hasScheme(dest) or std.mem.startsWith(u8, dest, "//")) return ""; │ │223 + const data = b.data orelse return ""; │ │224 const end = std.mem.indexOfAny(u8, dest, "?#") orelse dest.len; │ │225 if (end == 0) return ""; │ │226 const decoded = std.Uri.percentDecodeInPlace(try aa.dupe(u8, dest[0..end])); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │241 try segments.append(aa, part); │ │242 } │ │243 const path = try std.mem.join(aa, "/", segments.items); │ │242 - const route = b.data.filesRoute(path, 0) orelse return ""; │ │244 + const route = data.filesRoute(path, 0) orelse return ""; │ │245 return std.fmt.allocPrint(aa, "a:{s}", .{try route.toUrl(b.page_arena)});│ │246 } │ │247 }; │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/ui/widget.zig│ ╰─────────────────╯ ╭──────────────────────────────────────────────╮ │63 repo_comment: ui.Repo.Comment.Item, │ │64 copyable_text: CopyableText, │ │65 patch_source: ui.Repo.Patches.Source, │ │66 + home_about: ui.Home.About.View, │ │67 home_users: ui.Home.Users.View, │ │68 home_repos: ui.Home.Repos.View, │ │69 auth_tab: ui.Home.Header.AuthTab.View,│ ╰──────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │112 // whether moving up should return to the page header │ │113 pub fn atTop(self: *Widget, root_focus: *Focus) bool { │ │114 return switch (self.*) { │ │114 - inline .home_users, .home_repos, .flow_box_scroll, .home_settings, .auth_login, .auth_logout, .quit, .repo_files, .repo_commits, .diff_view, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo => |*view| view.atTop(), │ │115 + inline .home_about, .home_users, .home_repos, .flow_box_scroll, .home_settings, .auth_login, .auth_logout, .quit, .repo_files, .repo_commits, .diff_view, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo => |*view| view.atTop(),│ │116 inline .home_auth, .repo_patch_detail => |*view| view.atTop(root_focus), │ │117 else => false, │ │118 }; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯