121 lines
3.0 KiB
Go
121 lines
3.0 KiB
Go
package publish
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"gitea.maximumdirect.net/eric/distributor/internal/config"
|
|
"gitea.maximumdirect.net/eric/distributor/internal/link"
|
|
"gitea.maximumdirect.net/eric/distributor/internal/state"
|
|
)
|
|
|
|
func PlanLinks(req Request, outputs []Output) ([]Output, string, error) {
|
|
if req.Links == nil {
|
|
return outputs, "", nil
|
|
}
|
|
if err := link.ValidateHTTPURL(req.Links.BaseURL); err != nil {
|
|
return nil, "", fmt.Errorf("link base URL: %w", err)
|
|
}
|
|
linked := make([]Output, 0, len(outputs))
|
|
for _, output := range outputs {
|
|
outputURL, err := OutputURL(req.Links.BaseURL, req.DestinationBundlePath, output.DestinationPath)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
output.URL = outputURL
|
|
linked = append(linked, output)
|
|
}
|
|
return linked, primaryURL(linked, req.Links.Primary), nil
|
|
}
|
|
|
|
func OutputURL(baseURL, destinationBundlePath, outputPath string) (string, error) {
|
|
parsed, err := url.Parse(baseURL)
|
|
if err != nil {
|
|
return "", fmt.Errorf("link base URL: %w", err)
|
|
}
|
|
segments := pathSegments(parsed.Path)
|
|
segments = append(segments, pathSegments(destinationBundlePath)...)
|
|
outputSegments := pathSegments(outputPath)
|
|
trailingSlash := false
|
|
if len(outputSegments) > 0 && outputSegments[len(outputSegments)-1] == "index.html" {
|
|
outputSegments = outputSegments[:len(outputSegments)-1]
|
|
trailingSlash = true
|
|
}
|
|
segments = append(segments, outputSegments...)
|
|
parsed.Path = urlPath(segments, trailingSlash)
|
|
parsed.RawPath = ""
|
|
return parsed.String(), nil
|
|
}
|
|
|
|
func pathSegments(value string) []string {
|
|
trimmed := strings.Trim(value, "/")
|
|
if trimmed == "" {
|
|
return nil
|
|
}
|
|
return strings.Split(trimmed, "/")
|
|
}
|
|
|
|
func urlPath(segments []string, trailingSlash bool) string {
|
|
if len(segments) == 0 {
|
|
return "/"
|
|
}
|
|
path := "/" + strings.Join(segments, "/")
|
|
if trailingSlash && !strings.HasSuffix(path, "/") {
|
|
path += "/"
|
|
}
|
|
return path
|
|
}
|
|
|
|
func primaryURL(outputs []Output, policy string) string {
|
|
switch policy {
|
|
case config.LinkPrimaryHTML:
|
|
return firstGeneratedHTMLURL(outputs)
|
|
case config.LinkPrimarySource:
|
|
return firstSourceURL(outputs)
|
|
default:
|
|
if url := firstIndexURL(outputs); url != "" {
|
|
return url
|
|
}
|
|
if url := firstGeneratedHTMLURL(outputs); url != "" {
|
|
return url
|
|
}
|
|
return firstSourceURL(outputs)
|
|
}
|
|
}
|
|
|
|
func firstIndexURL(outputs []Output) string {
|
|
for _, output := range outputs {
|
|
if isIndexOutput(output.DestinationPath) {
|
|
return output.URL
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func firstGeneratedHTMLURL(outputs []Output) string {
|
|
for _, output := range outputs {
|
|
if output.Kind == state.OutputKindGenerated && isHTMLOutput(output.DestinationPath) {
|
|
return output.URL
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func firstSourceURL(outputs []Output) string {
|
|
for _, output := range outputs {
|
|
if output.Kind == state.OutputKindSource {
|
|
return output.URL
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func isIndexOutput(path string) bool {
|
|
return path == "index.html" || strings.HasSuffix(path, "/index.html")
|
|
}
|
|
|
|
func isHTMLOutput(path string) bool {
|
|
return strings.HasSuffix(path, ".html")
|
|
}
|