internal/httpd

namelast commitupdated
account.go web: a stale session's mint or grant gets a sign-in link back to the form 10 days ago
account_test.go web: mark-read dispatches notifications read 9 days ago
accounts.go web: new-issue form keeps milestone/assignee and a refused create 10 days ago
accounts_test.go web, store: final-review wording, header and range-diff fixes 10 days ago
activity.go httpd, web: month labels on the contribution grid 20 days ago
activity_test.go httpd, web: month labels on the contribution grid 20 days ago
admin.go control: the payloads other surfaces decode are named types 1 month ago
admin_test.go httpd, gitd: pack generation takes a slot; ls-refs does not 10 days ago
adminusers.go web: a stale session's mint or grant gets a sign-in link back to the form 10 days ago
anchors_test.go httpd, gitd: pack generation takes a slot; ls-refs does not 10 days ago
api.go control: expiring credentials cannot run credential-minting commands 10 days ago
apilimit.go http.trusted_proxies, and a cap on verification mail per account 1 month ago
apilimit_test.go httpd: rate limit the JSON API 1 month ago
apiread.go build log --follow: the follow says a restart ended it 15 days ago
atom.go web, store, policy, wiki: Atom feeds for releases, commits, and an owner's activity 1 month ago
atom_test.go web, store, policy, wiki: Atom feeds for releases, commits, and an owner's activity 1 month ago
badge.go build cancel: withdraw a queued build 1 month ago
badgepng.go Serve build badges as PNG as well as SVG 1 month ago
badgepng_test.go Serve build badges as PNG as well as SVG 1 month ago
buildpages_test.go web: builds page offers an org-mode badge snippet 10 days ago
builds.go web: step fold shows the step's first line; changelog: deploy order 10 days ago
builds_test.go builds: separate runs queued at different times 17 days ago
checkorigin_test.go httpd, gitd: pack generation takes a slot; ls-refs does not 10 days ago
chip_test.go httpd, web: a chip tone per scheme, and an underline where a link shares its line 19 days ago
clientip_test.go httpd, gitd: pack generation takes a slot; ls-refs does not 10 days ago
compare.go web: fork owners can open an MR from mrs and compare pages 10 days ago
compress.go build log --follow: end a queued follow, stream only on GET 15 days ago
compress_test.go httpd: gzipWriter passes a flush through 15 days ago
confirm.go web: resolve a snippet before checking its confirmation 26 days ago
control.go web: a stale session's mint or grant gets a sign-in link back to the form 10 days ago
cookieclear_test.go web: a suspended account cannot mail itself a session 1 month ago
crumbs_test.go web: directory crumbs on blob and blame pages link to the tree 1 month ago
dashpins.go web: the dashboard is three columns 19 days ago
dashpins_test.go control: move the feed-line sentence renderer from httpd, so the CLI can share it 10 days ago
depspage_test.go web: one timestamp format, with the zone named 26 days ago
diff.go web: keep an added line's leading dash in the diff 1 month ago
diff_test.go web: keep an added line's leading dash in the diff 1 month ago
emptystates_test.go web: drop CLI commands from four empty states, per the register 10 days ago
explorepage_test.go explore: name the filter, its count and a way out 17 days ago
facets.go web: a facet with nothing under it leaves the column 19 days ago
facets_test.go web: a facet with nothing under it leaves the column 19 days ago
facts.go store, control: build list gets --ref, --status and --job filters 20 days ago
filenav.go web: a file navigator beside blob, blame and edit 19 days ago
filenav_test.go web: a file navigator beside blob, blame and edit 19 days ago
filters.go issue list and mr list: filter by label, assignee, author, milestone 1 month ago
flash.go httpd: the login return path refuses a leading /\ 10 days ago
flash_test.go httpd: the login return path refuses a leading /\ 10 days ago
fonts_test.go httpd, gitd: pack generation takes a slot; ls-refs does not 10 days ago
headings_test.go web: a rendered document's headings sit under the page's own 1 month ago
healthz.go http: /healthz 1 month ago
inputlabels_test.go web: the topics-remove field gets a label, and a test that would have caught it 1 month ago
issueactions.go web: a failed form action's reason rides a one-shot cookie, not the URL 1 month ago
issuecreate_test.go tests: token and issue-form tests pass a nil pack limiter to New 10 days ago
labels.go web: the labels page hides an empty colour column 26 days ago
langs.go web: repository facts on the code page 1 month ago
lfs.go lfs: tokens carry the key's fingerprint pin beside its id 10 days ago
lfsauth_test.go lfs: tokens carry the key's fingerprint pin beside its id 10 days ago
logincookie_test.go tests: newer callers pass a nil pack limiter to New 10 days ago
logindisabled_test.go httpd, gitd: pack generation takes a slot; ls-refs does not 10 days ago
mractions.go web: queued merge state, merge-when-ready and cancel buttons on the MR page 9 days ago
mrpage_test.go web: Discussion heading before the comment thread on issue and MR pages 10 days ago
mrrangediff.go web, store: final-review wording, header and range-diff fixes 10 days ago
mrrangediff_test.go web, store: final-review wording, header and range-diff fixes 10 days ago
mrslist_test.go web: fork owners can open an MR from mrs and compare pages 10 days ago
mrsrow_test.go web: fork owners can open an MR from mrs and compare pages 10 days ago
notfound_test.go web: the ten findings from the forge comparison 19 days ago
notifyweb.go web: mark-read dispatches notifications read 9 days ago
orglabels.go web: org label and milestone pages under /{org}/-/, org mark on repository pages 27 days ago
orgrender_test.go web: the ten findings from the forge comparison 19 days ago
orgweb.go web: interface guidelines fixes 15 days ago
ownerpage_test.go control: move the feed-line sentence renderer from httpd, so the CLI can share it 10 days ago
packlimit_test.go httpd: web archives take a pack slot 10 days ago
page.go httpd: drop the rail's dead pinned-repo loop 19 days ago
pages.go pages: a directory redirect cannot leave the site 1 month ago
pagesredirect_test.go pages: a directory redirect cannot leave the site 1 month ago
palette_test.go web: rewrite the stylesheet on measured tokens 21 days ago
preview.go web: preview markup before writing it 19 days ago
railanon_test.go web: Explore is a rail square at every width 16 days ago
readme.go web: the owner page dispatches profile show 1 month ago
reauth_test.go web: a stale session's mint or grant gets a sign-in link back to the form 10 days ago
releaseactions.go web: preview markup before writing it 19 days ago
rendered.go web: the ten findings from the forge comparison 19 days ago
rendered_test.go web: the ten findings from the forge comparison 19 days ago
repohead_test.go web: watch button names all three states, muted included 10 days ago
routes.go web: range-diff page for a merge request's revisions 10 days ago
routes_test.go httpd, gitd: pack generation takes a slot; ls-refs does not 10 days ago
searchweb.go web: the rail is an icon column 20 days ago
searchweb_test.go web: search scope caption is permanent; document the tab zero-count rule 10 days ago
settings.go web: a stale session's mint or grant gets a sign-in link back to the form 10 days ago
sidecol_test.go web: the side column is a disclosure below 62rem 19 days ago
smart.go packlimit: log refusals once a minute per transport 10 days ago
snippets.go profile: reorder the tabs, and fold bookmarks and snippets in 17 days ago
theme.go web: the ten findings from the forge comparison 19 days ago
theme_test.go web: the ten findings from the forge comparison 19 days ago
topics.go web: topic and kind columns on explore and search 19 days ago
topics_test.go web: topic and kind columns on explore and search 19 days ago
trailingslash_test.go web: a trailing-slash redirect cannot leave the site 18 days ago
web.go web: a stale session's mint or grant gets a sign-in link back to the form 10 days ago
wiki.go wiki: a link to an existing non-page file resolves to _raw, not the page route 10 days ago
wiki_test.go wiki: a link to an existing non-page file resolves to _raw, not the page route 10 days ago
package httpd

import (
	"html/template"
	"path"
	"strings"

	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"

	"gitbay.org/gitbay/internal/gitutil"
)

// rewriteRelativeLinks makes relative hrefs and srcs in rendered repo
// content resolve on the forge: links go to blob pages, images to raw.
// go-org exports .org links as .html, so an .html target whose .org (or
// .md) source exists in the tree maps back to the source file.
func rewriteRelativeLinks(rendered template.HTML, p repoPage, baseDir string) template.HTML {
	ctx := &html.Node{Type: html.ElementNode, Data: "div", DataAtom: atom.Div}
	nodes, err := html.ParseFragment(strings.NewReader(string(rendered)), ctx)
	if err != nil {
		return rendered
	}
	var walk func(*html.Node)
	walk = func(n *html.Node) {
		if n.Type == html.ElementNode {
			for i, a := range n.Attr {
				isHref := a.Key == "href" && n.Data == "a"
				isSrc := a.Key == "src" && (n.Data == "img" || n.Data == "video" || n.Data == "source")
				if !isHref && !isSrc {
					continue
				}
				v := a.Val
				if v == "" || strings.Contains(v, "://") || strings.HasPrefix(v, "/") ||
					strings.HasPrefix(v, "#") || strings.HasPrefix(v, "mailto:") ||
					strings.HasPrefix(v, "data:") {
					continue
				}
				target := path.Clean(path.Join(baseDir, v))
				if strings.HasPrefix(target, "..") {
					continue
				}
				if isSrc {
					n.Attr[i].Val = "/" + p.Repo.Path() + "/raw/" + p.Ref + "/" + target
					continue
				}
				// .html from org/markdown exports maps back to the source.
				if strings.HasSuffix(target, ".html") {
					stem := strings.TrimSuffix(target, ".html")
					for _, ext := range []string{".org", ".md"} {
						if _, err := gitutil.ReadBlob(p.Dir, p.Ref, stem+ext, 1); err == nil {
							target = stem + ext
							break
						}
					}
				}
				n.Attr[i].Val = "/" + p.Repo.Path() + "/blob/" + p.Ref + "/" + target
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			walk(c)
		}
	}
	var out strings.Builder
	for _, n := range nodes {
		walk(n)
		if err := html.Render(&out, n); err != nil {
			return rendered
		}
	}
	return template.HTML(out.String())
}