Fix resolving of URLs in markdown (#401)

Path-only URLs need an absolute reference to be resolved against for printing in markdown
Previously we resolved against the URL to the resource we were operating on (eg comment or issue URL).
The markdown renderer in the web UI resolves all such URLs relative to the repo base URL. This PR adopts this behaviour in tea, by trimming the URL to a repo base URL via regex.

This makes a custom patch to our markdown renderer `glamour` obsolete, which turned out to be an incorrect patch, meaning we can make use of upstream glamour again.

Co-authored-by: Norwin <git@nroo.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/401
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: 6543 <6543@obermui.de>
Co-authored-by: Norwin <noerw@noreply.gitea.io>
Co-committed-by: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
Norwin 2021-12-03 02:59:02 +08:00 committed by 6543
parent dc16643e0d
commit d2295828d0
15 changed files with 28 additions and 34 deletions

2
go.mod
View File

@ -37,5 +37,3 @@ require (
golang.org/x/tools v0.1.5 // indirect
gopkg.in/yaml.v2 v2.4.0
)
replace github.com/charmbracelet/glamour => github.com/noerw/glamour v0.3.0-patch

4
go.sum
View File

@ -39,6 +39,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/charmbracelet/glamour v0.3.0 h1:3H+ZrKlSg8s+WU6V7eF2eRVYt8lCueffbi7r2+ffGkc=
github.com/charmbracelet/glamour v0.3.0/go.mod h1:TzF0koPZhqq0YVBNL100cPHznAAjVj7fksX2RInwjGw=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
@ -129,8 +131,6 @@ github.com/muesli/termenv v0.8.1/go.mod h1:kzt/D/4a88RoheZmwfqorY3A+tnsSMA9HJC/f
github.com/muesli/termenv v0.9.0 h1:wnbOaGz+LUR3jNT0zOzinPnyDaCZUQRZj9GxK8eRVl8=
github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtlyx2mBw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/noerw/glamour v0.3.0-patch h1:yc3wdbUIySok6KYeX5BtWnlj+PvP1uYeCeTSwq2rtSw=
github.com/noerw/glamour v0.3.0-patch/go.mod h1:TzF0koPZhqq0YVBNL100cPHznAAjVj7fksX2RInwjGw=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

View File

@ -15,7 +15,7 @@ import (
func Comments(comments []*gitea.Comment) {
var baseURL string
if len(comments) != 0 {
baseURL = comments[0].HTMLURL
baseURL = getRepoURL(comments[0].HTMLURL)
}
var out = make([]string, len(comments))
@ -32,7 +32,7 @@ func Comments(comments []*gitea.Comment) {
// Comment renders a comment to stdout
func Comment(c *gitea.Comment) {
outputMarkdown(formatComment(c), c.HTMLURL)
outputMarkdown(formatComment(c), getRepoURL(c.HTMLURL))
}
func formatComment(c *gitea.Comment) string {

View File

@ -6,12 +6,20 @@ package print
import (
"fmt"
"regexp"
"time"
"code.gitea.io/sdk/gitea"
"github.com/muesli/termenv"
)
// captures the repo URL part <host>/<owner>/<repo> of an url
var repoURLRegex = regexp.MustCompile("^([[:alnum:]]+://[^/]+(?:/[[:alnum:]]+){2})/.*")
func getRepoURL(resourceURL string) string {
return repoURLRegex.ReplaceAllString(resourceURL, "$1/")
}
// formatSize get kb in int and return string
func formatSize(kb int64) string {
if kb < 1024 {

View File

@ -28,7 +28,7 @@ func IssueDetails(issue *gitea.Issue, reactions []*gitea.Reaction) {
out += fmt.Sprintf("\n---\n\n%s\n", formatReactions(reactions))
}
outputMarkdown(out, issue.HTMLURL)
outputMarkdown(out, getRepoURL(issue.HTMLURL))
}
func formatReactions(reactions []*gitea.Reaction) string {

View File

@ -64,7 +64,7 @@ func PullDetails(pr *gitea.PullRequest, reviews []*gitea.PullReview, ciStatus *g
}
}
outputMarkdown(out, pr.HTMLURL)
outputMarkdown(out, getRepoURL(pr.HTMLURL))
}
func formatPRHead(pr *gitea.PullRequest) string {

View File

@ -6,10 +6,10 @@
<a href="https://pkg.go.dev/github.com/charmbracelet/glamour?tab=doc"><img src="https://godoc.org/github.com/golang/gddo?status.svg" alt="GoDoc"></a>
<a href="https://github.com/charmbracelet/glamour/actions"><img src="https://github.com/charmbracelet/glamour/workflows/build/badge.svg" alt="Build Status"></a>
<a href="https://coveralls.io/github/charmbracelet/glamour?branch=master"><img src="https://coveralls.io/repos/github/charmbracelet/glamour/badge.svg?branch=master" alt="Coverage Status"></a>
<a href="https://goreportcard.com/report/charmbracelet/glamour"><img src="https://goreportcard.com/badge/charmbracelet/glamour" alt="Go ReportCard"></a>
<a href="http://goreportcard.com/report/charmbracelet/glamour"><img src="http://goreportcard.com/badge/charmbracelet/glamour" alt="Go ReportCard"></a>
</p>
Stylesheet-based markdown rendering for your CLI apps.
Write handsome command-line tools with *Glamour*.
![Glamour dark style example](https://stuff.charm.sh/glamour/glamour-example.png)

View File

@ -129,9 +129,6 @@ func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element {
}
if node.Parent().(*ast.List).IsOrdered() {
e = l
if node.Parent().(*ast.List).Start != 1 {
e += uint(node.Parent().(*ast.List).Start) - 1
}
}
post := "\n"
@ -156,7 +153,6 @@ func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element {
return Element{
Exiting: post,
Renderer: &ItemElement{
IsOrdered: node.Parent().(*ast.List).IsOrdered(),
Enumeration: e,
},
}

View File

@ -25,7 +25,7 @@ func (e *ImageElement) Render(w io.Writer, ctx RenderContext) error {
}
if len(e.URL) > 0 {
el := &BaseElement{
Token: resolveURL(e.BaseURL, e.URL),
Token: resolveRelativeURL(e.BaseURL, e.URL),
Prefix: " ",
Style: ctx.options.Styles.Image,
}

View File

@ -64,7 +64,7 @@ func (e *LinkElement) Render(w io.Writer, ctx RenderContext) error {
}
el := &BaseElement{
Token: resolveURL(e.BaseURL, e.URL),
Token: resolveRelativeURL(e.BaseURL, e.URL),
Prefix: pre,
Style: style,
}

View File

@ -7,13 +7,12 @@ import (
// An ItemElement is used to render items inside a list.
type ItemElement struct {
IsOrdered bool
Enumeration uint
}
func (e *ItemElement) Render(w io.Writer, ctx RenderContext) error {
var el *BaseElement
if e.IsOrdered {
if e.Enumeration > 0 {
el = &BaseElement{
Style: ctx.options.Styles.Enumeration,
Prefix: strconv.FormatInt(int64(e.Enumeration), 10),

View File

@ -38,7 +38,7 @@ func (e *ParagraphElement) Finish(w io.Writer, ctx RenderContext) error {
mw := NewMarginWriter(ctx, w, rules)
if len(strings.TrimSpace(bs.Current().Block.String())) > 0 {
flow := wordwrap.NewWriter(int(bs.Width(ctx)))
flow.KeepNewlines = ctx.options.PreserveNewLines
flow.KeepNewlines = false
_, _ = flow.Write(bs.Current().Block.Bytes())
flow.Close()

View File

@ -3,6 +3,7 @@ package ansi
import (
"io"
"net/url"
"strings"
"github.com/muesli/termenv"
east "github.com/yuin/goldmark-emoji/ast"
@ -16,7 +17,6 @@ import (
type Options struct {
BaseURL string
WordWrap int
PreserveNewLines bool
ColorProfile termenv.Profile
Styles StyleConfig
}
@ -149,7 +149,7 @@ func isChild(node ast.Node) bool {
return false
}
func resolveURL(baseURL string, rel string) string {
func resolveRelativeURL(baseURL string, rel string) string {
u, err := url.Parse(rel)
if err != nil {
return rel
@ -157,6 +157,7 @@ func resolveURL(baseURL string, rel string) string {
if u.IsAbs() {
return rel
}
u.Path = strings.TrimPrefix(u.Path, "/")
base, err := url.Parse(baseURL)
if err != nil {

View File

@ -185,14 +185,6 @@ func WithWordWrap(wordWrap int) TermRendererOption {
}
}
// WithWordWrap sets a TermRenderer's word wrap.
func WithPreservedNewLines() TermRendererOption {
return func(tr *TermRenderer) error {
tr.ansiOptions.PreserveNewLines = true
return nil
}
}
// WithEmoji sets a TermRenderer's emoji rendering.
func WithEmoji() TermRendererOption {
return func(tr *TermRenderer) error {

2
vendor/modules.txt vendored
View File

@ -74,7 +74,7 @@ github.com/araddon/dateparse
# github.com/aymerick/douceur v0.2.0
github.com/aymerick/douceur/css
github.com/aymerick/douceur/parser
# github.com/charmbracelet/glamour v0.3.0 => github.com/noerw/glamour v0.3.0-patch
# github.com/charmbracelet/glamour v0.3.0
github.com/charmbracelet/glamour
github.com/charmbracelet/glamour/ansi
# github.com/cpuguy83/go-md2man/v2 v2.0.1