+20
-7
pkg/appview/readme/source.go
+20
-7
pkg/appview/readme/source.go
···
10
10
type Platform string
11
11
12
12
const (
13
-
PlatformGitHub Platform = "github"
14
-
PlatformGitLab Platform = "gitlab"
15
-
PlatformTangled Platform = "tangled"
13
+
PlatformGitHub Platform = "github"
14
+
PlatformGitLab Platform = "gitlab"
15
+
PlatformTangled Platform = "tangled"
16
+
PlatformCodeberg Platform = "codeberg"
16
17
)
17
18
18
19
// ParseSourceURL extracts platform, user, and repo from a source repository URL.
···
38
39
39
40
host := strings.ToLower(parsed.Host)
40
41
41
-
switch {
42
-
case host == "github.com":
42
+
switch host {
43
+
case "github.com":
43
44
// GitHub: github.com/{user}/{repo}
44
45
parts := strings.SplitN(path, "/", 3)
45
46
if len(parts) < 2 || parts[0] == "" || parts[1] == "" {
···
47
48
}
48
49
return PlatformGitHub, parts[0], parts[1], true
49
50
50
-
case host == "gitlab.com":
51
+
case "gitlab.com":
51
52
// GitLab: gitlab.com/{user}/{repo} or gitlab.com/{group}/{subgroup}/{repo}
52
53
// For nested groups, user = everything except last part, repo = last part
53
54
lastSlash := strings.LastIndex(path, "/")
···
61
62
}
62
63
return PlatformGitLab, user, repo, true
63
64
64
-
case host == "tangled.org" || host == "tangled.sh":
65
+
case "tangled.org", "tangled.sh":
65
66
// Tangled: tangled.org/{user}/{repo} or tangled.sh/@{user}/{repo} (legacy)
66
67
// Strip leading @ from user if present
67
68
path = strings.TrimPrefix(path, "@")
···
70
71
return "", "", "", false
71
72
}
72
73
return PlatformTangled, parts[0], parts[1], true
74
+
75
+
case "codeberg.org":
76
+
// Codeberg: codeberg.org/{user}/{repo}
77
+
parts := strings.SplitN(path, "/", 3)
78
+
if len(parts) < 2 || parts[0] == "" || parts[1] == "" {
79
+
return "", "", "", false
80
+
}
81
+
return PlatformCodeberg, parts[0], parts[1], true
73
82
74
83
default:
75
84
return "", "", "", false
···
96
105
case PlatformTangled:
97
106
// https://tangled.org/{user}/{repo}/raw/{branch}/README.md
98
107
return fmt.Sprintf("https://tangled.org/%s/%s/raw/%s/README.md", user, repo, branch)
108
+
109
+
case PlatformCodeberg:
110
+
// https://codeberg.org/{user}/{repo}/raw/branch/{branch}/README.md
111
+
return fmt.Sprintf("https://codeberg.org/%s/%s/raw/branch/%s/README.md", user, repo, branch)
99
112
100
113
default:
101
114
return ""
+18
pkg/appview/readme/source_test.go
+18
pkg/appview/readme/source_test.go
···
120
120
wantOK: true,
121
121
},
122
122
123
+
// Codeberg
124
+
{
125
+
name: "codeberg standard",
126
+
sourceURL: "https://codeberg.org/user/repo",
127
+
wantPlatform: PlatformCodeberg,
128
+
wantUser: "user",
129
+
wantRepo: "repo",
130
+
wantOK: true,
131
+
},
132
+
123
133
// Unsupported / Invalid
124
134
{
125
135
name: "unsupported platform",
···
213
223
sourceURL: "https://tangled.org/@user/repo",
214
224
branch: "main",
215
225
want: "https://tangled.org/user/repo/raw/main/README.md",
226
+
},
227
+
228
+
// Codeberg
229
+
{
230
+
name: "codeberg main",
231
+
sourceURL: "https://codeberg.org/user/repo",
232
+
branch: "main",
233
+
want: "https://codeberg.org/user/repo/raw/branch/main/README.md",
216
234
},
217
235
218
236
// Unsupported