summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorjaqra <48099350+jaqra@users.noreply.github.com>2019-09-10 12:03:30 +0300
committerLauris BH <lauris.buksis@zzdats.lv>2019-09-10 12:03:30 +0300
commit7e17424c7e189f91d4f1b35e2504141b1e8116f6 (patch)
treef5d0711fa6f368b9aa751113b4ee868d281e803a /modules
parent7eacdcf39a4de3a5ea2f234f9444753ee40d8d35 (diff)
downloadgitea-7e17424c7e189f91d4f1b35e2504141b1e8116f6.tar.gz
gitea-7e17424c7e189f91d4f1b35e2504141b1e8116f6.zip
Make link last commit massages in repository home page and commit tables (#8006)
* Make link last commit massages in repository home page and commit tables * Use RenderCommitMessageLink instead surround with a * deleted __debug_bin file * Exclude email to link from latest commit title * Exclude email processor from commit table Co-Authored-By: mrsdizzie <info@mrsdizzie.com> * Add class parameter to a html element creator functions. Make links underline dashed that are not commit * fix tests * Show dashed underline when also not hovered
Diffstat (limited to 'modules')
-rw-r--r--modules/markup/html.go73
-rw-r--r--modules/markup/html_internal_test.go36
-rw-r--r--modules/templates/helper.go33
3 files changed, 106 insertions, 36 deletions
diff --git a/modules/markup/html.go b/modules/markup/html.go
index ff5b1a76e6..f07993bc4c 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -211,6 +211,40 @@ func RenderCommitMessage(
return ctx.postProcess(rawHTML)
}
+var commitMessageSubjectProcessors = []processor{
+ fullIssuePatternProcessor,
+ fullSha1PatternProcessor,
+ linkProcessor,
+ mentionProcessor,
+ issueIndexPatternProcessor,
+ crossReferenceIssueIndexPatternProcessor,
+ sha1CurrentPatternProcessor,
+}
+
+// RenderCommitMessageSubject will use the same logic as PostProcess and
+// RenderCommitMessage, but will disable the shortLinkProcessor and
+// emailAddressProcessor, will add a defaultLinkProcessor if defaultLink is set,
+// which changes every text node into a link to the passed default link.
+func RenderCommitMessageSubject(
+ rawHTML []byte,
+ urlPrefix, defaultLink string,
+ metas map[string]string,
+) ([]byte, error) {
+ ctx := &postProcessCtx{
+ metas: metas,
+ urlPrefix: urlPrefix,
+ procs: commitMessageSubjectProcessors,
+ }
+ if defaultLink != "" {
+ // we don't have to fear data races, because being
+ // commitMessageSubjectProcessors of fixed len and cap, every time we
+ // append something to it the slice is realloc+copied, so append always
+ // generates the slice ex-novo.
+ ctx.procs = append(ctx.procs, genDefaultLinkProcessor(defaultLink))
+ }
+ return ctx.postProcess(rawHTML)
+}
+
// RenderDescriptionHTML will use similar logic as PostProcess, but will
// use a single special linkProcessor.
func RenderDescriptionHTML(
@@ -296,12 +330,17 @@ func (ctx *postProcessCtx) textNode(node *html.Node) {
}
}
-func createLink(href, content string) *html.Node {
+func createLink(href, content, class string) *html.Node {
a := &html.Node{
Type: html.ElementNode,
Data: atom.A.String(),
Attr: []html.Attribute{{Key: "href", Val: href}},
}
+
+ if class != "" {
+ a.Attr = append(a.Attr, html.Attribute{Key: "class", Val: class})
+ }
+
text := &html.Node{
Type: html.TextNode,
Data: content,
@@ -311,12 +350,17 @@ func createLink(href, content string) *html.Node {
return a
}
-func createCodeLink(href, content string) *html.Node {
+func createCodeLink(href, content, class string) *html.Node {
a := &html.Node{
Type: html.ElementNode,
Data: atom.A.String(),
Attr: []html.Attribute{{Key: "href", Val: href}},
}
+
+ if class != "" {
+ a.Attr = append(a.Attr, html.Attribute{Key: "class", Val: class})
+ }
+
text := &html.Node{
Type: html.TextNode,
Data: content,
@@ -364,7 +408,7 @@ func mentionProcessor(_ *postProcessCtx, node *html.Node) {
}
// Replace the mention with a link to the specified user.
mention := node.Data[m[2]:m[3]]
- replaceContent(node, m[2], m[3], createLink(util.URLJoin(setting.AppURL, mention[1:]), mention))
+ replaceContent(node, m[2], m[3], createLink(util.URLJoin(setting.AppURL, mention[1:]), mention, "mention"))
}
func shortLinkProcessor(ctx *postProcessCtx, node *html.Node) {
@@ -541,11 +585,11 @@ func fullIssuePatternProcessor(ctx *postProcessCtx, node *html.Node) {
if matchOrg == ctx.metas["user"] && matchRepo == ctx.metas["repo"] {
// TODO if m[4]:m[5] is not nil, then link is to a comment,
// and we should indicate that in the text somehow
- replaceContent(node, m[0], m[1], createLink(link, id))
+ replaceContent(node, m[0], m[1], createLink(link, id, "issue"))
} else {
orgRepoID := matchOrg + "/" + matchRepo + id
- replaceContent(node, m[0], m[1], createLink(link, orgRepoID))
+ replaceContent(node, m[0], m[1], createLink(link, orgRepoID, "issue"))
}
}
@@ -573,9 +617,9 @@ func issueIndexPatternProcessor(ctx *postProcessCtx, node *html.Node) {
} else {
ctx.metas["index"] = id[1:]
}
- link = createLink(com.Expand(ctx.metas["format"], ctx.metas), id)
+ link = createLink(com.Expand(ctx.metas["format"], ctx.metas), id, "issue")
} else {
- link = createLink(util.URLJoin(setting.AppURL, ctx.metas["user"], ctx.metas["repo"], "issues", id[1:]), id)
+ link = createLink(util.URLJoin(setting.AppURL, ctx.metas["user"], ctx.metas["repo"], "issues", id[1:]), id, "issue")
}
replaceContent(node, match[2], match[3], link)
}
@@ -591,7 +635,7 @@ func crossReferenceIssueIndexPatternProcessor(ctx *postProcessCtx, node *html.No
repo, issue := parts[0], parts[1]
replaceContent(node, m[2], m[3],
- createLink(util.URLJoin(setting.AppURL, repo, "issues", issue), ref))
+ createLink(util.URLJoin(setting.AppURL, repo, "issues", issue), ref, issue))
}
// fullSha1PatternProcessor renders SHA containing URLs
@@ -642,7 +686,7 @@ func fullSha1PatternProcessor(ctx *postProcessCtx, node *html.Node) {
text += " (" + hash + ")"
}
- replaceContent(node, start, end, createCodeLink(urlFull, text))
+ replaceContent(node, start, end, createCodeLink(urlFull, text, "commit"))
}
// sha1CurrentPatternProcessor renders SHA1 strings to corresponding links that
@@ -672,7 +716,7 @@ func sha1CurrentPatternProcessor(ctx *postProcessCtx, node *html.Node) {
}
replaceContent(node, m[2], m[3],
- createCodeLink(util.URLJoin(setting.AppURL, ctx.metas["user"], ctx.metas["repo"], "commit", hash), base.ShortSha(hash)))
+ createCodeLink(util.URLJoin(setting.AppURL, ctx.metas["user"], ctx.metas["repo"], "commit", hash), base.ShortSha(hash), "commit"))
}
// emailAddressProcessor replaces raw email addresses with a mailto: link.
@@ -682,7 +726,7 @@ func emailAddressProcessor(ctx *postProcessCtx, node *html.Node) {
return
}
mail := node.Data[m[2]:m[3]]
- replaceContent(node, m[2], m[3], createLink("mailto:"+mail, mail))
+ replaceContent(node, m[2], m[3], createLink("mailto:"+mail, mail, "mailto"))
}
// linkProcessor creates links for any HTTP or HTTPS URL not captured by
@@ -693,7 +737,7 @@ func linkProcessor(ctx *postProcessCtx, node *html.Node) {
return
}
uri := node.Data[m[0]:m[1]]
- replaceContent(node, m[0], m[1], createLink(uri, uri))
+ replaceContent(node, m[0], m[1], createLink(uri, uri, "link"))
}
func genDefaultLinkProcessor(defaultLink string) processor {
@@ -707,7 +751,10 @@ func genDefaultLinkProcessor(defaultLink string) processor {
node.Type = html.ElementNode
node.Data = "a"
node.DataAtom = atom.A
- node.Attr = []html.Attribute{{Key: "href", Val: defaultLink}}
+ node.Attr = []html.Attribute{
+ {Key: "href", Val: defaultLink},
+ {Key: "class", Val: "default-link"},
+ }
node.FirstChild, node.LastChild = ch, ch
}
}
diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go
index bb47ba3b2c..2824ce3e68 100644
--- a/modules/markup/html_internal_test.go
+++ b/modules/markup/html_internal_test.go
@@ -20,18 +20,22 @@ const Repo = "gogits/gogs"
const AppSubURL = AppURL + Repo + "/"
// alphanumLink an HTML link to an alphanumeric-style issue
-func alphanumIssueLink(baseURL string, name string) string {
- return link(util.URLJoin(baseURL, name), name)
+func alphanumIssueLink(baseURL, class, name string) string {
+ return link(util.URLJoin(baseURL, name), class, name)
}
// numericLink an HTML to a numeric-style issue
-func numericIssueLink(baseURL string, index int) string {
- return link(util.URLJoin(baseURL, strconv.Itoa(index)), fmt.Sprintf("#%d", index))
+func numericIssueLink(baseURL, class string, index int) string {
+ return link(util.URLJoin(baseURL, strconv.Itoa(index)), class, fmt.Sprintf("#%d", index))
}
// link an HTML link
-func link(href, contents string) string {
- return fmt.Sprintf("<a href=\"%s\">%s</a>", href, contents)
+func link(href, class, contents string) string {
+ if class != "" {
+ class = " class=\"" + class + "\""
+ }
+
+ return fmt.Sprintf("<a href=\"%s\"%s>%s</a>", href, class, contents)
}
var numericMetas = map[string]string{
@@ -89,13 +93,13 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
test := func(s, expectedFmt string, indices ...int) {
links := make([]interface{}, len(indices))
for i, index := range indices {
- links[i] = numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), index)
+ links[i] = numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), "issue", index)
}
expectedNil := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNil, &postProcessCtx{metas: localMetas})
for i, index := range indices {
- links[i] = numericIssueLink("https://someurl.com/someUser/someRepo/", index)
+ links[i] = numericIssueLink("https://someurl.com/someUser/someRepo/", "issue", index)
}
expectedNum := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNum, &postProcessCtx{metas: numericMetas})
@@ -158,7 +162,7 @@ func TestRender_IssueIndexPattern4(t *testing.T) {
test := func(s, expectedFmt string, names ...string) {
links := make([]interface{}, len(names))
for i, name := range names {
- links[i] = alphanumIssueLink("https://someurl.com/someUser/someRepo/", name)
+ links[i] = alphanumIssueLink("https://someurl.com/someUser/someRepo/", "issue", name)
}
expected := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expected, &postProcessCtx{metas: alphanumericMetas})
@@ -197,17 +201,17 @@ func TestRender_AutoLink(t *testing.T) {
// render valid issue URLs
test(util.URLJoin(setting.AppSubURL, "issues", "3333"),
- numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), 3333))
+ numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), "issue", 3333))
// render valid commit URLs
tmp := util.URLJoin(AppSubURL, "commit", "d8a994ef243349f321568f9e36d5c3f444b99cae")
- test(tmp, "<a href=\""+tmp+"\"><code class=\"nohighlight\">d8a994ef24</code></a>")
+ test(tmp, "<a href=\""+tmp+"\" class=\"commit\"><code class=\"nohighlight\">d8a994ef24</code></a>")
tmp += "#diff-2"
- test(tmp, "<a href=\""+tmp+"\"><code class=\"nohighlight\">d8a994ef24 (diff-2)</code></a>")
+ test(tmp, "<a href=\""+tmp+"\" class=\"commit\"><code class=\"nohighlight\">d8a994ef24 (diff-2)</code></a>")
// render other commit URLs
tmp = "https://external-link.gitea.io/go-gitea/gitea/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2"
- test(tmp, "<a href=\""+tmp+"\"><code class=\"nohighlight\">d8a994ef24 (diff-2)</code></a>")
+ test(tmp, "<a href=\""+tmp+"\" class=\"commit\"><code class=\"nohighlight\">d8a994ef24 (diff-2)</code></a>")
}
func TestRender_FullIssueURLs(t *testing.T) {
@@ -228,11 +232,11 @@ func TestRender_FullIssueURLs(t *testing.T) {
test("Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6",
"Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6")
test("Look here http://localhost:3000/person/repo/issues/4",
- `Look here <a href="http://localhost:3000/person/repo/issues/4">person/repo#4</a>`)
+ `Look here <a href="http://localhost:3000/person/repo/issues/4" class="issue">person/repo#4</a>`)
test("http://localhost:3000/person/repo/issues/4#issuecomment-1234",
- `<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234">person/repo#4</a>`)
+ `<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234" class="issue">person/repo#4</a>`)
test("http://localhost:3000/gogits/gogs/issues/4",
- `<a href="http://localhost:3000/gogits/gogs/issues/4">#4</a>`)
+ `<a href="http://localhost:3000/gogits/gogs/issues/4" class="issue">#4</a>`)
}
func TestRegExp_issueNumericPattern(t *testing.T) {
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 147df3a788..ba61dd5eef 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -118,13 +118,14 @@ func NewFuncMap() []template.FuncMap {
"EscapePound": func(str string) string {
return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str)
},
- "PathEscapeSegments": util.PathEscapeSegments,
- "URLJoin": util.URLJoin,
- "RenderCommitMessage": RenderCommitMessage,
- "RenderCommitMessageLink": RenderCommitMessageLink,
- "RenderCommitBody": RenderCommitBody,
- "RenderNote": RenderNote,
- "IsMultilineCommitMessage": IsMultilineCommitMessage,
+ "PathEscapeSegments": util.PathEscapeSegments,
+ "URLJoin": util.URLJoin,
+ "RenderCommitMessage": RenderCommitMessage,
+ "RenderCommitMessageLink": RenderCommitMessageLink,
+ "RenderCommitMessageLinkSubject": RenderCommitMessageLinkSubject,
+ "RenderCommitBody": RenderCommitBody,
+ "RenderNote": RenderNote,
+ "IsMultilineCommitMessage": IsMultilineCommitMessage,
"ThemeColorMetaTag": func() string {
return setting.UI.ThemeColorMetaTag
},
@@ -322,6 +323,24 @@ func RenderCommitMessageLink(msg, urlPrefix, urlDefault string, metas map[string
return template.HTML(msgLines[0])
}
+// RenderCommitMessageLinkSubject renders commit message as a XXS-safe link to
+// the provided default url, handling for special links without email to links.
+func RenderCommitMessageLinkSubject(msg, urlPrefix, urlDefault string, metas map[string]string) template.HTML {
+ cleanMsg := template.HTMLEscapeString(msg)
+ // we can safely assume that it will not return any error, since there
+ // shouldn't be any special HTML.
+ fullMessage, err := markup.RenderCommitMessageSubject([]byte(cleanMsg), urlPrefix, urlDefault, metas)
+ if err != nil {
+ log.Error("RenderCommitMessageSubject: %v", err)
+ return ""
+ }
+ msgLines := strings.Split(strings.TrimSpace(string(fullMessage)), "\n")
+ if len(msgLines) == 0 {
+ return template.HTML("")
+ }
+ return template.HTML(msgLines[0])
+}
+
// RenderCommitBody extracts the body of a commit message without its title.
func RenderCommitBody(msg, urlPrefix string, metas map[string]string) template.HTML {
cleanMsg := template.HTMLEscapeString(msg)