diff --git a/README.md b/README.md index 7823d998c5e3dd740154138153142d5b21d54119..b526756dff25a1db2927a6e2ec653de0d97dcff9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ugit -ugit logo +ugit logo Minimal git server @@ -29,4 +29,4 @@ ## License [MIT](LICENSE) -Lots of inspiration and some starting code used from [gitea](https://github.com/go-gitea/gitea) [(MIT)](https://github.com/go-gitea/gitea/blob/eba9c0ce48c7d43910eb77db74c6648157663ceb/LICENSE), [wish](https://github.com/charmbracelet/wish) [(MIT)](https://github.com/charmbracelet/wish/blob/3e6f92a166118390484ce4a0904114b375b9e485/LICENSE), and [legit](https://github.com/icyphox/legit) [(MIT)](https://github.com/icyphox/legit/blob/bdfc973207a67a3b217c130520d53373d088763c/license). +Lots of inspiration and some starting code used from [wish](https://github.com/charmbracelet/wish) [(MIT)](https://github.com/charmbracelet/wish/blob/3e6f92a166118390484ce4a0904114b375b9e485/LICENSE) and [legit](https://github.com/icyphox/legit) [(MIT)](https://github.com/icyphox/legit/blob/bdfc973207a67a3b217c130520d53373d088763c/license). diff --git a/flake.nix b/flake.nix index 15612ff4af2cbcfca2fb495339da7f74e3532a49..f9c52d0f7d42103274b68ff8a46d7a2c022dd0e1 100644 --- a/flake.nix +++ b/flake.nix @@ -31,7 +31,7 @@ name = pname; path = ./.; }); subPackages = ["cmd/ugitd"]; - vendorHash = "sha256-2vIccmJs6YitRndccQOnUuFZCIbwzi0NfRzbixaLVTo="; + vendorHash = "sha256-E4cwC6c0d+HvHldqGYiWdPEdS2fch6imvAXzxb2MMdY="; meta = with pkgs.lib; { description = "Minimal git server"; homepage = "https://git.jolheiser.com/ugit"; diff --git a/go.mod b/go.mod index 28b39d6469c5a5cab4ef6859e77e1b11660633f6..3af97fb05ebeb5960238f3b62b6af33eee6ebb08 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ github.com/peterbourgon/ff/v3 v3.4.0 github.com/yuin/goldmark v1.6.0 github.com/yuin/goldmark-emoji v1.0.2 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc - golang.org/x/net v0.19.0 ) require ( @@ -48,6 +47,7 @@ github.com/skeema/knownhosts v1.2.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect golang.org/x/crypto v0.17.0 // indirect golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/tools v0.16.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/internal/html/markdown.go b/internal/html/markdown.go index c4c8d5fc9f6aa904eac08f8d403fd84f1f3570b8..e109162de66398d42dc38e2d8442c37f28b3d7e4 100644 --- a/internal/html/markdown.go +++ b/internal/html/markdown.go @@ -2,12 +2,7 @@ package html import ( "bytes" - "fmt" - "golang.org/x/net/html" - "io" - "net/url" "path/filepath" - "strings" "go.jolheiser.com/ugit/internal/git" @@ -15,23 +10,17 @@ chromahtml "github.com/alecthomas/chroma/v2/formatters/html" "github.com/yuin/goldmark" emoji "github.com/yuin/goldmark-emoji" highlighting "github.com/yuin/goldmark-highlighting/v2" - "github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" goldmarkhtml "github.com/yuin/goldmark/renderer/html" - "github.com/yuin/goldmark/text" - "github.com/yuin/goldmark/util" ) -var markdown = goldmark.New( +var Markdown = goldmark.New( goldmark.WithRendererOptions( goldmarkhtml.WithUnsafe(), ), goldmark.WithParserOptions( parser.WithAutoHeadingID(), - parser.WithASTTransformers( - util.Prioritized(astTransformer{}, 100), - ), ), goldmark.WithExtensions( extension.GFM, @@ -59,23 +48,11 @@ } } if readme != "" { - ctx := parser.NewContext() - mdCtx := markdownContext{ - repo: repo.Name(), - ref: ref, - path: path, - } - ctx.Set(renderContextKey, mdCtx) var buf bytes.Buffer - if err := markdown.Convert([]byte(readme), &buf, parser.WithContext(ctx)); err != nil { + if err := Markdown.Convert([]byte(readme), &buf); err != nil { return "", err } - var out bytes.Buffer - if err := postProcess(buf.String(), mdCtx, &out); err != nil { - return "", err - } - - return out.String(), nil + return buf.String(), nil } for _, md := range []string{"README.txt", "README", "readme.txt", "readme"} { @@ -87,128 +64,3 @@ } return "", nil } - -var renderContextKey = parser.NewContextKey() - -type markdownContext struct { - repo string - ref string - path string -} - -type astTransformer struct{} - -func (a astTransformer) Transform(node *ast.Document, _ text.Reader, pc parser.Context) { - _ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) { - if !entering { - return ast.WalkContinue, nil - } - - ctx := pc.Get(renderContextKey).(markdownContext) - - switch v := n.(type) { - case *ast.Image: - link := v.Destination - if len(link) > 0 && !bytes.HasPrefix(link, []byte("http")) { - v.Destination = []byte(resolveLink(ctx.repo, ctx.ref, ctx.path, string(link)) + "?raw&pretty") - } - - parent := n.Parent() - if _, ok := parent.(*ast.Link); !ok && parent != nil { - next := n.NextSibling() - wrapper := ast.NewLink() - wrapper.Destination = v.Destination - wrapper.Title = v.Title - wrapper.SetAttributeString("target", []byte("_blank")) - img := ast.NewImage(ast.NewLink()) - img.Destination = link - img.Title = v.Title - for _, attr := range v.Attributes() { - img.SetAttribute(attr.Name, attr.Value) - } - for child := v.FirstChild(); child != nil; { - nextChild := child.NextSibling() - img.AppendChild(img, child) - child = nextChild - } - wrapper.AppendChild(wrapper, img) - wrapper.SetNextSibling(next) - parent.ReplaceChild(parent, n, wrapper) - v.SetNextSibling(next) - } - case *ast.Link: - link := v.Destination - if len(link) > 0 && !bytes.HasPrefix(link, []byte("http")) && link[0] != '#' && !bytes.HasPrefix(link, []byte("mailto")) { - v.Destination = []byte(resolveLink(ctx.repo, ctx.ref, ctx.path, string(link))) - } - } - - return ast.WalkContinue, nil - }) -} - -func postProcess(in string, ctx markdownContext, out io.Writer) error { - node, err := html.Parse(strings.NewReader("" + in + " 0 && !strings.HasPrefix(attr.Val, "http") && !strings.HasPrefix(attr.Val, "data:image/") { - attr.Val = resolveLink(ctx.repo, ctx.ref, ctx.path, attr.Val) + "?raw&pretty" - } - node.Attr[i] = attr - } - } - for n := node.FirstChild; n != nil; n = n.NextSibling { - process(ctx, n) - } -} - -func resolveLink(repo, ref, path, link string) string { - baseURL, err := url.Parse(fmt.Sprintf("/%s/tree/%s/%s", repo, ref, path)) - if err != nil { - return "" - } - linkURL, err := url.Parse(link) - if err != nil { - return "" - } - return baseURL.ResolveReference(linkURL).String() -} diff --git a/internal/html/repo_commit.templ b/internal/html/repo_commit.templ index bb95a59fae886baa92f3de71e39949ff5b0abe7d..7f07f145081601e442a16b27556e1ce276f54949 100644 --- a/internal/html/repo_commit.templ +++ b/internal/html/repo_commit.templ @@ -21,19 +21,7 @@
{ humanize.Time(rcc.Commit.When) }
{ fmt.Sprintf("%d changed files, %d additions(+), %d deletions(-)", rcc.Commit.Stats.Changed, rcc.Commit.Stats.Additions, rcc.Commit.Stats.Deletions) }
for _, file := range rcc.Commit.Files { -
- { string(file.Action[0]) } - { " " } - if file.From.Path != "" { - { file.From.Path } - } - if file.From.Path != "" && file.To.Path != "" { - { " -> " } - } - if file.To.Path != "" { - { file.To.Path } - } -
+
{ string(file.Action[0]) }{ " " }{ file.From.Path }{ " -> " }{ file.To.Path }
@templ.Raw(file.Patch)
} } diff --git a/internal/html/repo_commit_templ.go b/internal/html/repo_commit_templ.go index 49c39c56f407fc6bb805e9aa465764d74745604e..8a48de28e800dc0136b43650eb499947f4eb50cb 100644 --- a/internal/html/repo_commit_templ.go +++ b/internal/html/repo_commit_templ.go @@ -219,11 +219,38 @@ if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, file := range rcc.Commit.Files { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var18 string + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(string(file.Action[0])) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 23, Col: 82} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var19 string + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(" ") + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 23, Col: 96} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(file.Action)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var18 string - templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(string(file.Action[0])) + var templ_7745c5c3_Var21 string + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 24, Col: 77} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 23, Col: 320} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var19 string - templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(" ") + var templ_7745c5c3_Var22 string + templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 25, Col: 9} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 23, Col: 334} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var21 string - templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(file.From.Path) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 27, Col: 227} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } + var templ_7745c5c3_Var23 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s", rcc.RepoHeaderComponentContext.Name, file.To.Commit, file.To.Path)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var23))) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err } - if file.From.Path != "" && file.To.Path != "" { - var templ_7745c5c3_Var22 string - templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(" -> ") - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 30, Col: 13} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err } - if file.To.Path != "" { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var24 string - templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 33, Col: 221} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } + var templ_7745c5c3_Var24 string + templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(file.To.Path) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_commit.templ`, Line: 23, Col: 552} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err }