104 lines
2.8 KiB
Go
104 lines
2.8 KiB
Go
package readme
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// Platform represents a supported Git hosting platform
|
|
type Platform string
|
|
|
|
const (
|
|
PlatformGitHub Platform = "github"
|
|
PlatformGitLab Platform = "gitlab"
|
|
PlatformTangled Platform = "tangled"
|
|
)
|
|
|
|
// ParseSourceURL extracts platform, user, and repo from a source repository URL.
|
|
// Returns ok=false if the URL is not a recognized pattern.
|
|
func ParseSourceURL(sourceURL string) (platform Platform, user, repo string, ok bool) {
|
|
if sourceURL == "" {
|
|
return "", "", "", false
|
|
}
|
|
|
|
parsed, err := url.Parse(sourceURL)
|
|
if err != nil {
|
|
return "", "", "", false
|
|
}
|
|
|
|
// Normalize: remove trailing slash and .git suffix
|
|
path := strings.TrimSuffix(parsed.Path, "/")
|
|
path = strings.TrimSuffix(path, ".git")
|
|
path = strings.TrimPrefix(path, "/")
|
|
|
|
if path == "" {
|
|
return "", "", "", false
|
|
}
|
|
|
|
host := strings.ToLower(parsed.Host)
|
|
|
|
switch {
|
|
case host == "github.com":
|
|
// GitHub: github.com/{user}/{repo}
|
|
parts := strings.SplitN(path, "/", 3)
|
|
if len(parts) < 2 || parts[0] == "" || parts[1] == "" {
|
|
return "", "", "", false
|
|
}
|
|
return PlatformGitHub, parts[0], parts[1], true
|
|
|
|
case host == "gitlab.com":
|
|
// GitLab: gitlab.com/{user}/{repo} or gitlab.com/{group}/{subgroup}/{repo}
|
|
// For nested groups, user = everything except last part, repo = last part
|
|
lastSlash := strings.LastIndex(path, "/")
|
|
if lastSlash == -1 || lastSlash == 0 {
|
|
return "", "", "", false
|
|
}
|
|
user = path[:lastSlash]
|
|
repo = path[lastSlash+1:]
|
|
if user == "" || repo == "" {
|
|
return "", "", "", false
|
|
}
|
|
return PlatformGitLab, user, repo, true
|
|
|
|
case host == "tangled.org" || host == "tangled.sh":
|
|
// Tangled: tangled.org/{user}/{repo} or tangled.sh/@{user}/{repo} (legacy)
|
|
// Strip leading @ from user if present
|
|
path = strings.TrimPrefix(path, "@")
|
|
parts := strings.SplitN(path, "/", 3)
|
|
if len(parts) < 2 || parts[0] == "" || parts[1] == "" {
|
|
return "", "", "", false
|
|
}
|
|
return PlatformTangled, parts[0], parts[1], true
|
|
|
|
default:
|
|
return "", "", "", false
|
|
}
|
|
}
|
|
|
|
// DeriveReadmeURL converts a source repository URL to a raw README URL.
|
|
// Returns empty string if platform is not supported.
|
|
func DeriveReadmeURL(sourceURL, branch string) string {
|
|
platform, user, repo, ok := ParseSourceURL(sourceURL)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
|
|
switch platform {
|
|
case PlatformGitHub:
|
|
// https://raw.githubusercontent.com/{user}/{repo}/refs/heads/{branch}/README.md
|
|
return fmt.Sprintf("https://raw.githubusercontent.com/%s/%s/refs/heads/%s/README.md", user, repo, branch)
|
|
|
|
case PlatformGitLab:
|
|
// https://gitlab.com/{user}/{repo}/-/raw/{branch}/README.md
|
|
return fmt.Sprintf("https://gitlab.com/%s/%s/-/raw/%s/README.md", user, repo, branch)
|
|
|
|
case PlatformTangled:
|
|
// https://tangled.org/{user}/{repo}/raw/{branch}/README.md
|
|
return fmt.Sprintf("https://tangled.org/%s/%s/raw/%s/README.md", user, repo, branch)
|
|
|
|
default:
|
|
return ""
|
|
}
|
|
}
|