@@ -25,9 +25,6 @@ const (
2525	IssueNameStyleRegexp        =  "regexp" 
2626)
2727
28- // CSS class for action keywords (e.g. "closes: #1") 
29- const  keywordClass  =  "issue-keyword" 
30- 
3128type  globalVarsType  struct  {
3229	hashCurrentPattern       * regexp.Regexp 
3330	shortLinkPattern         * regexp.Regexp 
@@ -39,6 +36,7 @@ type globalVarsType struct {
3936	emojiShortCodeRegex      * regexp.Regexp 
4037	issueFullPattern         * regexp.Regexp 
4138	filesChangedFullPattern  * regexp.Regexp 
39+ 	codePreviewPattern       * regexp.Regexp 
4240
4341	tagCleaner  * regexp.Regexp 
4442	nulCleaner  * strings.Replacer 
@@ -88,6 +86,9 @@ var globalVars = sync.OnceValue[*globalVarsType](func() *globalVarsType {
8886	// example: https://domain/org/repo/pulls/27/files#hash 
8987	v .filesChangedFullPattern  =  regexp .MustCompile (`https?://(?:\S+/)[\w_.-]+/[\w_.-]+/pulls/((?:\w{1,10}-)?[1-9][0-9]*)/files([\?|#](\S+)?)?\b` )
9088
89+ 	// codePreviewPattern matches "http://domain/.../{owner}/{repo}/src/commit/{commit}/{filepath}#L10-L20" 
90+ 	v .codePreviewPattern  =  regexp .MustCompile (`https?://\S+/([^\s/]+)/([^\s/]+)/src/commit/([0-9a-f]{7,64})(/\S+)#(L\d+(-L\d+)?)` )
91+ 
9192	v .tagCleaner  =  regexp .MustCompile (`<((?:/?\w+/\w+)|(?:/[\w ]+/)|(/?[hH][tT][mM][lL]\b)|(/?[hH][eE][aA][dD]\b))` )
9293	v .nulCleaner  =  strings .NewReplacer ("\000 " , "" )
9394	return  v 
@@ -164,11 +165,7 @@ var defaultProcessors = []processor{
164165// emails with HTML links, parsing shortlinks in the format of [[Link]], like 
165166// MediaWiki, linking issues in the format #ID, and mentions in the format 
166167// @user, and others. 
167- func  PostProcess (
168- 	ctx  * RenderContext ,
169- 	input  io.Reader ,
170- 	output  io.Writer ,
171- ) error  {
168+ func  PostProcess (ctx  * RenderContext , input  io.Reader , output  io.Writer ) error  {
172169	return  postProcess (ctx , defaultProcessors , input , output )
173170}
174171
@@ -189,10 +186,7 @@ var commitMessageProcessors = []processor{
189186// RenderCommitMessage will use the same logic as PostProcess, but will disable 
190187// the shortLinkProcessor and will add a defaultLinkProcessor if defaultLink is 
191188// set, which changes every text node into a link to the passed default link. 
192- func  RenderCommitMessage (
193- 	ctx  * RenderContext ,
194- 	content  string ,
195- ) (string , error ) {
189+ func  RenderCommitMessage (ctx  * RenderContext , content  string ) (string , error ) {
196190	procs  :=  commitMessageProcessors 
197191	return  renderProcessString (ctx , procs , content )
198192}
@@ -219,10 +213,7 @@ var emojiProcessors = []processor{
219213// RenderCommitMessage, but will disable the shortLinkProcessor and 
220214// emailAddressProcessor, will add a defaultLinkProcessor if defaultLink is set, 
221215// which changes every text node into a link to the passed default link. 
222- func  RenderCommitMessageSubject (
223- 	ctx  * RenderContext ,
224- 	defaultLink , content  string ,
225- ) (string , error ) {
216+ func  RenderCommitMessageSubject (ctx  * RenderContext , defaultLink , content  string ) (string , error ) {
226217	procs  :=  slices .Clone (commitMessageSubjectProcessors )
227218	procs  =  append (procs , func (ctx  * RenderContext , node  * html.Node ) {
228219		ch  :=  & html.Node {Parent : node , Type : html .TextNode , Data : node .Data }
@@ -236,10 +227,7 @@ func RenderCommitMessageSubject(
236227}
237228
238229// RenderIssueTitle to process title on individual issue/pull page 
239- func  RenderIssueTitle (
240- 	ctx  * RenderContext ,
241- 	title  string ,
242- ) (string , error ) {
230+ func  RenderIssueTitle (ctx  * RenderContext , title  string ) (string , error ) {
243231	// do not render other issue/commit links in an issue's title - which in most cases is already a link. 
244232	return  renderProcessString (ctx , []processor {
245233		emojiShortCodeProcessor ,
@@ -257,10 +245,7 @@ func renderProcessString(ctx *RenderContext, procs []processor, content string)
257245
258246// RenderDescriptionHTML will use similar logic as PostProcess, but will 
259247// use a single special linkProcessor. 
260- func  RenderDescriptionHTML (
261- 	ctx  * RenderContext ,
262- 	content  string ,
263- ) (string , error ) {
248+ func  RenderDescriptionHTML (ctx  * RenderContext , content  string ) (string , error ) {
264249	return  renderProcessString (ctx , []processor {
265250		descriptionLinkProcessor ,
266251		emojiShortCodeProcessor ,
@@ -270,10 +255,7 @@ func RenderDescriptionHTML(
270255
271256// RenderEmoji for when we want to just process emoji and shortcodes 
272257// in various places it isn't already run through the normal markdown processor 
273- func  RenderEmoji (
274- 	ctx  * RenderContext ,
275- 	content  string ,
276- ) (string , error ) {
258+ func  RenderEmoji (ctx  * RenderContext , content  string ) (string , error ) {
277259	return  renderProcessString (ctx , emojiProcessors , content )
278260}
279261
@@ -405,13 +387,16 @@ func processTextNodes(ctx *RenderContext, procs []processor, node *html.Node) {
405387}
406388
407389// createKeyword() renders a highlighted version of an action keyword 
408- func  createKeyword (content  string ) * html.Node  {
390+ func  createKeyword (ctx  * RenderContext , content  string ) * html.Node  {
391+ 	// CSS class for action keywords (e.g. "closes: #1") 
392+ 	const  keywordClass  =  "issue-keyword" 
393+ 
409394	span  :=  & html.Node {
410395		Type : html .ElementNode ,
411396		Data : atom .Span .String (),
412397		Attr : []html.Attribute {},
413398	}
414- 	span .Attr  =  append (span .Attr , html. Attribute { Key :  "class" , Val :  keywordClass } )
399+ 	span .Attr  =  append (span .Attr , ctx . RenderInternal . NodeSafeAttr ( "class" , keywordClass ) )
415400
416401	text  :=  & html.Node {
417402		Type : html .TextNode ,
@@ -422,7 +407,7 @@ func createKeyword(content string) *html.Node {
422407	return  span 
423408}
424409
425- func  createLink (href , content , class  string ) * html.Node  {
410+ func  createLink (ctx   * RenderContext ,  href , content , class  string ) * html.Node  {
426411	a  :=  & html.Node {
427412		Type : html .ElementNode ,
428413		Data : atom .A .String (),
@@ -432,7 +417,7 @@ func createLink(href, content, class string) *html.Node {
432417		a .Attr  =  append (a .Attr , html.Attribute {Key : "data-markdown-generated-content" })
433418	}
434419	if  class  !=  ""  {
435- 		a .Attr  =  append (a .Attr , html. Attribute { Key :  "class" , Val :  class } )
420+ 		a .Attr  =  append (a .Attr , ctx . RenderInternal . NodeSafeAttr ( "class" , class ) )
436421	}
437422
438423	text  :=  & html.Node {
0 commit comments