From 54ac43aed612056b671637025a4b54dcb9269ae8 Mon Sep 17 00:00:00 2001 From: moshyfawn Date: Tue, 6 Jan 2026 23:15:28 -0500 Subject: [PATCH] appview/reporesolver: fix current directory extraction for tree paths path.Dir on extractPathAfterRef returned the parent directory, which broke relative link resolution in markdown when viewing directories. extractCurrentDir now handles blob and tree paths separately: blob paths return the parent dir, tree paths return the directory itself Signed-off-by: moshyfawn --- appview/reporesolver/resolver.go | 27 ++++++++++++++++++++++++++- appview/reporesolver/resolver_test.go | 22 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 appview/reporesolver/resolver_test.go diff --git a/appview/reporesolver/resolver.go b/appview/reporesolver/resolver.go index 2a924cb9..c7fe61ed 100644 --- a/appview/reporesolver/resolver.go +++ b/appview/reporesolver/resolver.go @@ -63,7 +63,7 @@ func (rr *RepoResolver) GetRepoInfo(r *http.Request, user *oauth.User) repoinfo. } // get dir/ref - currentDir := path.Dir(extractPathAfterRef(r.URL.EscapedPath())) + currentDir := extractCurrentDir(r.URL.EscapedPath()) ref := chi.URLParam(r, "ref") repoAt := repo.RepoAt() @@ -132,6 +132,31 @@ func (rr *RepoResolver) GetRepoInfo(r *http.Request, user *oauth.User) repoinfo. return repoInfo } +// extractCurrentDir gets the current directory for markdown link resolution. +// for blob paths, returns the parent dir. for tree paths, returns the path itself. +// +// /@user/repo/blob/main/docs/README.md => docs +// /@user/repo/tree/main/docs => docs +func extractCurrentDir(fullPath string) string { + fullPath = strings.TrimPrefix(fullPath, "/") + + blobPattern := regexp.MustCompile(`blob/[^/]+/(.*)$`) + if matches := blobPattern.FindStringSubmatch(fullPath); len(matches) > 1 { + return path.Dir(matches[1]) + } + + treePattern := regexp.MustCompile(`tree/[^/]+/(.*)$`) + if matches := treePattern.FindStringSubmatch(fullPath); len(matches) > 1 { + dir := strings.TrimSuffix(matches[1], "/") + if dir == "" { + return "." + } + return dir + } + + return "." +} + // extractPathAfterRef gets the actual repository path // after the ref. for example: // diff --git a/appview/reporesolver/resolver_test.go b/appview/reporesolver/resolver_test.go new file mode 100644 index 00000000..5a620aaf --- /dev/null +++ b/appview/reporesolver/resolver_test.go @@ -0,0 +1,22 @@ +package reporesolver + +import "testing" + +func TestExtractCurrentDir(t *testing.T) { + tests := []struct { + path string + want string + }{ + {"/@user/repo/blob/main/docs/README.md", "docs"}, + {"/@user/repo/blob/main/README.md", "."}, + {"/@user/repo/tree/main/docs", "docs"}, + {"/@user/repo/tree/main/docs/", "docs"}, + {"/@user/repo/tree/main", "."}, + } + + for _, tt := range tests { + if got := extractCurrentDir(tt.path); got != tt.want { + t.Errorf("extractCurrentDir(%q) = %q, want %q", tt.path, got, tt.want) + } + } +} -- 2.43.0