Files
2025-12-20 16:00:15 -06:00

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 ""
}
}