@@ -32,7 +32,6 @@ type globalVarsType struct {
32
32
comparePattern * regexp.Regexp
33
33
fullURLPattern * regexp.Regexp
34
34
emailRegex * regexp.Regexp
35
- blackfridayExtRegex * regexp.Regexp
36
35
emojiShortCodeRegex * regexp.Regexp
37
36
issueFullPattern * regexp.Regexp
38
37
filesChangedFullPattern * regexp.Regexp
@@ -74,9 +73,6 @@ var globalVars = sync.OnceValue(func() *globalVarsType {
74
73
// https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type%3Demail)
75
74
v .emailRegex = regexp .MustCompile ("(?:\\ s|^|\\ (|\\ [)([a-zA-Z0-9.!#$%&'*+\\ /=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\ .[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)(?:\\ s|$|\\ )|\\ ]|;|,|\\ ?|!|\\ .(\\ s|$))" )
76
75
77
- // blackfridayExtRegex is for blackfriday extensions create IDs like fn:user-content-footnote
78
- v .blackfridayExtRegex = regexp .MustCompile (`[^:]*:user-content-` )
79
-
80
76
// emojiShortCodeRegex find emoji by alias like :smile:
81
77
v .emojiShortCodeRegex = regexp .MustCompile (`:[-+\w]+:` )
82
78
@@ -94,17 +90,12 @@ var globalVars = sync.OnceValue(func() *globalVarsType {
94
90
return v
95
91
})
96
92
97
- // IsFullURLBytes reports whether link fits valid format.
98
- func IsFullURLBytes (link []byte ) bool {
99
- return globalVars ().fullURLPattern .Match (link )
100
- }
101
-
102
93
func IsFullURLString (link string ) bool {
103
94
return globalVars ().fullURLPattern .MatchString (link )
104
95
}
105
96
106
97
func IsNonEmptyRelativePath (link string ) bool {
107
- return link != "" && ! IsFullURLString (link ) && link [0 ] != '/' && link [ 0 ] != ' ?' && link [0 ] != '#'
98
+ return link != "" && ! IsFullURLString (link ) && link [0 ] != '?' && link [0 ] != '#'
108
99
}
109
100
110
101
// CustomLinkURLSchemes allows for additional schemes to be detected when parsing links within text
@@ -316,44 +307,38 @@ func isEmojiNode(node *html.Node) bool {
316
307
}
317
308
318
309
func visitNode (ctx * RenderContext , procs []processor , node * html.Node ) * html.Node {
319
- // Add user-content- to IDs and "#" links if they don't already have them
320
- for idx , attr := range node .Attr {
321
- val := strings .TrimPrefix (attr .Val , "#" )
322
- notHasPrefix := ! (strings .HasPrefix (val , "user-content-" ) || globalVars ().blackfridayExtRegex .MatchString (val ))
323
-
324
- if attr .Key == "id" && notHasPrefix {
325
- node .Attr [idx ].Val = "user-content-" + attr .Val
326
- }
327
-
328
- if attr .Key == "href" && strings .HasPrefix (attr .Val , "#" ) && notHasPrefix {
329
- node .Attr [idx ].Val = "#user-content-" + val
330
- }
331
- }
332
-
333
- switch node .Type {
334
- case html .TextNode :
310
+ if node .Type == html .TextNode {
335
311
for _ , proc := range procs {
336
312
proc (ctx , node ) // it might add siblings
337
313
}
314
+ return node .NextSibling
315
+ }
316
+ if node .Type != html .ElementNode {
317
+ return node .NextSibling
318
+ }
338
319
339
- case html .ElementNode :
340
- if isEmojiNode (node ) {
341
- // TextNode emoji will be converted to `<span class="emoji">`, then the next iteration will visit the "span"
342
- // if we don't stop it, it will go into the TextNode again and create an infinite recursion
343
- return node .NextSibling
344
- } else if node .Data == "code" || node .Data == "pre" {
345
- return node .NextSibling // ignore code and pre nodes
346
- } else if node .Data == "img" {
347
- return visitNodeImg (ctx , node )
348
- } else if node .Data == "video" {
349
- return visitNodeVideo (ctx , node )
350
- } else if node .Data == "a" {
351
- procs = emojiProcessors // Restrict text in links to emojis
352
- }
353
- for n := node .FirstChild ; n != nil ; {
354
- n = visitNode (ctx , procs , n )
355
- }
356
- default :
320
+ processNodeAttrID (node )
321
+
322
+ if isEmojiNode (node ) {
323
+ // TextNode emoji will be converted to `<span class="emoji">`, then the next iteration will visit the "span"
324
+ // if we don't stop it, it will go into the TextNode again and create an infinite recursion
325
+ return node .NextSibling
326
+ } else if node .Data == "code" || node .Data == "pre" {
327
+ return node .NextSibling // ignore code and pre nodes
328
+ } else if node .Data == "img" {
329
+ return visitNodeImg (ctx , node )
330
+ } else if node .Data == "video" {
331
+ return visitNodeVideo (ctx , node )
332
+ }
333
+
334
+ if node .Data == "a" {
335
+ processNodeA (ctx , node )
336
+ // only use emoji processors for the content in the "A" tag,
337
+ // because the content there is not processable, for example: the content is a commit id or a full URL.
338
+ procs = emojiProcessors
339
+ }
340
+ for n := node .FirstChild ; n != nil ; {
341
+ n = visitNode (ctx , procs , n )
357
342
}
358
343
return node .NextSibling
359
344
}
0 commit comments