Migration This is my new public git source viewer. Source coming soon. Please contact with concerns/bugs. Contact me

internal/core/nav.go

d658fcc4ea9f3bb562fd00dce8f863934560c56c · 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 }