genericURLWorkflowName derives a best-effort workflow name from a raw import URL. It uses the last non-empty path segment, stripping any well-known file extensions. If no useful name can be derived the constant "imported-workflow" is returned.
(rawURL string)
| 521 | // It uses the last non-empty path segment, stripping any well-known file extensions. |
| 522 | // If no useful name can be derived the constant "imported-workflow" is returned. |
| 523 | func genericURLWorkflowName(rawURL string) string { |
| 524 | parsed, err := url.Parse(rawURL) |
| 525 | if err != nil { |
| 526 | return "imported-workflow" |
| 527 | } |
| 528 | |
| 529 | // Walk path segments from the end looking for a non-empty one. |
| 530 | segments := strings.Split(strings.Trim(parsed.Path, "/"), "/") |
| 531 | for i := range slices.Backward(segments) { |
| 532 | seg := segments[i] |
| 533 | if seg == "" { |
| 534 | continue |
| 535 | } |
| 536 | // Strip known extensions: .md, .json, .yaml, .yml |
| 537 | for _, ext := range []string{".md", ".json", ".yaml", ".yml"} { |
| 538 | if s, ok := strings.CutSuffix(seg, ext); ok { |
| 539 | seg = s |
| 540 | break |
| 541 | } |
| 542 | } |
| 543 | if seg == "" { |
| 544 | continue |
| 545 | } |
| 546 | // URL-decode percent-encoded characters (e.g. %20 → space) before |
| 547 | // applying kebab-casing so that names like "My%20Workflow" become |
| 548 | // "my-workflow" rather than "my-20workflow". |
| 549 | if decoded, err := url.PathUnescape(seg); err == nil { |
| 550 | seg = decoded |
| 551 | } |
| 552 | return toKebabCase(seg) |
| 553 | } |
| 554 | return "imported-workflow" |
| 555 | } |