Migration
This is my new public git source viewer. Source coming soon. Please contact with concerns/bugs.
Contact me
internal/core/nav.go
main
· 2.1 KB · 70 lines
raw
| 1 | package core |
| 2 | |
| 3 | import "strings" |
| 4 | |
| 5 | // NavItem is one entry in the repo-scoped navigation -- the top tab bar |
| 6 | // and the page-nav chips both render the same slice, built from the route |
| 7 | // table so a new tab is a one-line addition to site/routes.go, not a |
| 8 | // second place to remember. |
| 9 | type NavItem struct { |
| 10 | Label string |
| 11 | Href string |
| 12 | Active bool |
| 13 | } |
| 14 | |
| 15 | // BuildNav derives the repo-scoped nav from every route whose NavLabel is |
| 16 | // set, in route-table order. current is the name of the route being |
| 17 | // served, used to mark the matching tab active. |
| 18 | func BuildNav(routes []Route, current, slug, ref string) []NavItem { |
| 19 | if slug == "" { |
| 20 | return nil |
| 21 | } |
| 22 | var items []NavItem |
| 23 | for _, rt := range routes { |
| 24 | if rt.Scope != ScopeRepo || rt.NavLabel == "" { |
| 25 | continue |
| 26 | } |
| 27 | items = append(items, NavItem{ |
| 28 | Label: rt.NavLabel, |
| 29 | Href: navHref(rt, slug, ref), |
| 30 | // The "repo" route (bare /{repo}/) renders tree.html at its |
| 31 | // root, same as "tree" does at path "" -- so the files tab |
| 32 | // lights up on both, even though "repo" carries no NavLabel |
| 33 | // of its own and never appears in this loop as a tab. |
| 34 | Active: rt.Name == current || (rt.Name == "tree" && current == "repo"), |
| 35 | }) |
| 36 | } |
| 37 | return items |
| 38 | } |
| 39 | |
| 40 | // navHref builds the href for a nav tab from its route pattern: the fixed |
| 41 | // segment right after {repo}, plus the ref if the route is ref-addressed |
| 42 | // ({rest...} or {rev}). Routes addressed only by {$} (graph, refs) link to |
| 43 | // their bare index instead. |
| 44 | func navHref(rt Route, slug, ref string) string { |
| 45 | seg := navSegment(rt.Pattern) |
| 46 | href := "/" + slug + "/" |
| 47 | if seg != "" { |
| 48 | href += seg + "/" |
| 49 | } |
| 50 | if strings.Contains(rt.Pattern, "{rest...}") || strings.Contains(rt.Pattern, "{rev}") { |
| 51 | href += ref |
| 52 | } |
| 53 | return href |
| 54 | } |
| 55 | |
| 56 | // navSegment extracts the literal path element between {repo} and the |
| 57 | // next wildcard, e.g. "GET /{repo}/tree/{rest...}" -> "tree". Returns "" |
| 58 | // for patterns with no such segment (e.g. "GET /{repo}/{$}"). |
| 59 | func navSegment(pattern string) string { |
| 60 | p := pattern |
| 61 | if i := strings.IndexByte(p, ' '); i >= 0 { |
| 62 | p = p[i+1:] |
| 63 | } |
| 64 | p = strings.TrimPrefix(p, "/{repo}/") |
| 65 | seg, _, _ := strings.Cut(p, "/") |
| 66 | if strings.HasPrefix(seg, "{") { |
| 67 | return "" |
| 68 | } |
| 69 | return seg |
| 70 | } |