@@ -211,6 +211,40 @@ func RenderCommitMessage(
211211 return ctx .postProcess (rawHTML )
212212}
213213
214+ var commitMessageSubjectProcessors = []processor {
215+ fullIssuePatternProcessor ,
216+ fullSha1PatternProcessor ,
217+ linkProcessor ,
218+ mentionProcessor ,
219+ issueIndexPatternProcessor ,
220+ crossReferenceIssueIndexPatternProcessor ,
221+ sha1CurrentPatternProcessor ,
222+ }
223+
224+ // RenderCommitMessageSubject will use the same logic as PostProcess and
225+ // RenderCommitMessage, but will disable the shortLinkProcessor and
226+ // emailAddressProcessor, will add a defaultLinkProcessor if defaultLink is set,
227+ // which changes every text node into a link to the passed default link.
228+ func RenderCommitMessageSubject (
229+ rawHTML []byte ,
230+ urlPrefix , defaultLink string ,
231+ metas map [string ]string ,
232+ ) ([]byte , error ) {
233+ ctx := & postProcessCtx {
234+ metas : metas ,
235+ urlPrefix : urlPrefix ,
236+ procs : commitMessageSubjectProcessors ,
237+ }
238+ if defaultLink != "" {
239+ // we don't have to fear data races, because being
240+ // commitMessageSubjectProcessors of fixed len and cap, every time we
241+ // append something to it the slice is realloc+copied, so append always
242+ // generates the slice ex-novo.
243+ ctx .procs = append (ctx .procs , genDefaultLinkProcessor (defaultLink ))
244+ }
245+ return ctx .postProcess (rawHTML )
246+ }
247+
214248// RenderDescriptionHTML will use similar logic as PostProcess, but will
215249// use a single special linkProcessor.
216250func RenderDescriptionHTML (
@@ -296,12 +330,17 @@ func (ctx *postProcessCtx) textNode(node *html.Node) {
296330 }
297331}
298332
299- func createLink (href , content string ) * html.Node {
333+ func createLink (href , content , class string ) * html.Node {
300334 a := & html.Node {
301335 Type : html .ElementNode ,
302336 Data : atom .A .String (),
303337 Attr : []html.Attribute {{Key : "href" , Val : href }},
304338 }
339+
340+ if class != "" {
341+ a .Attr = append (a .Attr , html.Attribute {Key : "class" , Val : class })
342+ }
343+
305344 text := & html.Node {
306345 Type : html .TextNode ,
307346 Data : content ,
@@ -311,12 +350,17 @@ func createLink(href, content string) *html.Node {
311350 return a
312351}
313352
314- func createCodeLink (href , content string ) * html.Node {
353+ func createCodeLink (href , content , class string ) * html.Node {
315354 a := & html.Node {
316355 Type : html .ElementNode ,
317356 Data : atom .A .String (),
318357 Attr : []html.Attribute {{Key : "href" , Val : href }},
319358 }
359+
360+ if class != "" {
361+ a .Attr = append (a .Attr , html.Attribute {Key : "class" , Val : class })
362+ }
363+
320364 text := & html.Node {
321365 Type : html .TextNode ,
322366 Data : content ,
@@ -364,7 +408,7 @@ func mentionProcessor(_ *postProcessCtx, node *html.Node) {
364408 }
365409 // Replace the mention with a link to the specified user.
366410 mention := node .Data [m [2 ]:m [3 ]]
367- replaceContent (node , m [2 ], m [3 ], createLink (util .URLJoin (setting .AppURL , mention [1 :]), mention ))
411+ replaceContent (node , m [2 ], m [3 ], createLink (util .URLJoin (setting .AppURL , mention [1 :]), mention , "mention" ))
368412}
369413
370414func shortLinkProcessor (ctx * postProcessCtx , node * html.Node ) {
@@ -541,11 +585,11 @@ func fullIssuePatternProcessor(ctx *postProcessCtx, node *html.Node) {
541585 if matchOrg == ctx .metas ["user" ] && matchRepo == ctx .metas ["repo" ] {
542586 // TODO if m[4]:m[5] is not nil, then link is to a comment,
543587 // and we should indicate that in the text somehow
544- replaceContent (node , m [0 ], m [1 ], createLink (link , id ))
588+ replaceContent (node , m [0 ], m [1 ], createLink (link , id , "issue" ))
545589
546590 } else {
547591 orgRepoID := matchOrg + "/" + matchRepo + id
548- replaceContent (node , m [0 ], m [1 ], createLink (link , orgRepoID ))
592+ replaceContent (node , m [0 ], m [1 ], createLink (link , orgRepoID , "issue" ))
549593 }
550594}
551595
@@ -573,9 +617,9 @@ func issueIndexPatternProcessor(ctx *postProcessCtx, node *html.Node) {
573617 } else {
574618 ctx .metas ["index" ] = id [1 :]
575619 }
576- link = createLink (com .Expand (ctx .metas ["format" ], ctx .metas ), id )
620+ link = createLink (com .Expand (ctx .metas ["format" ], ctx .metas ), id , "issue" )
577621 } else {
578- link = createLink (util .URLJoin (setting .AppURL , ctx .metas ["user" ], ctx .metas ["repo" ], "issues" , id [1 :]), id )
622+ link = createLink (util .URLJoin (setting .AppURL , ctx .metas ["user" ], ctx .metas ["repo" ], "issues" , id [1 :]), id , "issue" )
579623 }
580624 replaceContent (node , match [2 ], match [3 ], link )
581625}
@@ -591,7 +635,7 @@ func crossReferenceIssueIndexPatternProcessor(ctx *postProcessCtx, node *html.No
591635 repo , issue := parts [0 ], parts [1 ]
592636
593637 replaceContent (node , m [2 ], m [3 ],
594- createLink (util .URLJoin (setting .AppURL , repo , "issues" , issue ), ref ))
638+ createLink (util .URLJoin (setting .AppURL , repo , "issues" , issue ), ref , issue ))
595639}
596640
597641// fullSha1PatternProcessor renders SHA containing URLs
@@ -642,7 +686,7 @@ func fullSha1PatternProcessor(ctx *postProcessCtx, node *html.Node) {
642686 text += " (" + hash + ")"
643687 }
644688
645- replaceContent (node , start , end , createCodeLink (urlFull , text ))
689+ replaceContent (node , start , end , createCodeLink (urlFull , text , "commit" ))
646690}
647691
648692// sha1CurrentPatternProcessor renders SHA1 strings to corresponding links that
@@ -672,7 +716,7 @@ func sha1CurrentPatternProcessor(ctx *postProcessCtx, node *html.Node) {
672716 }
673717
674718 replaceContent (node , m [2 ], m [3 ],
675- createCodeLink (util .URLJoin (setting .AppURL , ctx .metas ["user" ], ctx .metas ["repo" ], "commit" , hash ), base .ShortSha (hash )))
719+ createCodeLink (util .URLJoin (setting .AppURL , ctx .metas ["user" ], ctx .metas ["repo" ], "commit" , hash ), base .ShortSha (hash ), "commit" ))
676720}
677721
678722// emailAddressProcessor replaces raw email addresses with a mailto: link.
@@ -682,7 +726,7 @@ func emailAddressProcessor(ctx *postProcessCtx, node *html.Node) {
682726 return
683727 }
684728 mail := node .Data [m [2 ]:m [3 ]]
685- replaceContent (node , m [2 ], m [3 ], createLink ("mailto:" + mail , mail ))
729+ replaceContent (node , m [2 ], m [3 ], createLink ("mailto:" + mail , mail , "mailto" ))
686730}
687731
688732// linkProcessor creates links for any HTTP or HTTPS URL not captured by
@@ -693,7 +737,7 @@ func linkProcessor(ctx *postProcessCtx, node *html.Node) {
693737 return
694738 }
695739 uri := node .Data [m [0 ]:m [1 ]]
696- replaceContent (node , m [0 ], m [1 ], createLink (uri , uri ))
740+ replaceContent (node , m [0 ], m [1 ], createLink (uri , uri , "link" ))
697741}
698742
699743func genDefaultLinkProcessor (defaultLink string ) processor {
@@ -707,7 +751,10 @@ func genDefaultLinkProcessor(defaultLink string) processor {
707751 node .Type = html .ElementNode
708752 node .Data = "a"
709753 node .DataAtom = atom .A
710- node .Attr = []html.Attribute {{Key : "href" , Val : defaultLink }}
754+ node .Attr = []html.Attribute {
755+ {Key : "href" , Val : defaultLink },
756+ {Key : "class" , Val : "default-link" },
757+ }
711758 node .FirstChild , node .LastChild = ch , ch
712759 }
713760}
0 commit comments