@@ -372,7 +372,42 @@ func postProcess(ctx *RenderContext, procs []processor, input io.Reader, output
372
372
return nil
373
373
}
374
374
375
- func visitNode (ctx * RenderContext , procs []processor , node * html.Node ) {
375
+ func handleNodeImg (ctx * RenderContext , img * html.Node ) {
376
+ for i , attr := range img .Attr {
377
+ if attr .Key != "src" {
378
+ continue
379
+ }
380
+
381
+ if attr .Val != "" && ! IsFullURLString (attr .Val ) && ! strings .HasPrefix (attr .Val , "/" ) {
382
+ attr .Val = util .URLJoin (ctx .Links .ResolveMediaLink (ctx .IsWiki ), attr .Val )
383
+
384
+ // By default, the "<img>" tag should also be clickable,
385
+ // because frontend use `<img>` to paste the re-scaled image into the markdown,
386
+ // so it must match the default markdown image behavior.
387
+ hasParentAnchor := false
388
+ for p := img .Parent ; p != nil ; p = p .Parent {
389
+ if hasParentAnchor = p .Type == html .ElementNode && p .Data == "a" ; hasParentAnchor {
390
+ break
391
+ }
392
+ }
393
+ if ! hasParentAnchor {
394
+ imgA := & html.Node {Type : html .ElementNode , Data : "a" , Attr : []html.Attribute {
395
+ {Key : "href" , Val : attr .Val },
396
+ {Key : "target" , Val : "_blank" },
397
+ }}
398
+ parent := img .Parent
399
+ imgNext := img .NextSibling
400
+ parent .RemoveChild (img )
401
+ parent .InsertBefore (imgA , imgNext )
402
+ imgA .AppendChild (img )
403
+ }
404
+ }
405
+ attr .Val = camoHandleLink (attr .Val )
406
+ img .Attr [i ] = attr
407
+ }
408
+ }
409
+
410
+ func visitNode (ctx * RenderContext , procs []processor , node * html.Node ) * html.Node {
376
411
// Add user-content- to IDs and "#" links if they don't already have them
377
412
for idx , attr := range node .Attr {
378
413
val := strings .TrimPrefix (attr .Val , "#" )
@@ -397,21 +432,14 @@ func visitNode(ctx *RenderContext, procs []processor, node *html.Node) {
397
432
textNode (ctx , procs , node )
398
433
case html .ElementNode :
399
434
if node .Data == "img" {
400
- for i , attr := range node .Attr {
401
- if attr .Key != "src" {
402
- continue
403
- }
404
- if len (attr .Val ) > 0 && ! IsFullURLString (attr .Val ) && ! strings .HasPrefix (attr .Val , "data:image/" ) {
405
- attr .Val = util .URLJoin (ctx .Links .ResolveMediaLink (ctx .IsWiki ), attr .Val )
406
- }
407
- attr .Val = camoHandleLink (attr .Val )
408
- node .Attr [i ] = attr
409
- }
435
+ next := node .NextSibling
436
+ handleNodeImg (ctx , node )
437
+ return next
410
438
} else if node .Data == "a" {
411
439
// Restrict text in links to emojis
412
440
procs = emojiProcessors
413
441
} else if node .Data == "code" || node .Data == "pre" {
414
- return
442
+ return node . NextSibling
415
443
} else if node .Data == "i" {
416
444
for _ , attr := range node .Attr {
417
445
if attr .Key != "class" {
@@ -434,11 +462,11 @@ func visitNode(ctx *RenderContext, procs []processor, node *html.Node) {
434
462
}
435
463
}
436
464
}
437
- for n := node .FirstChild ; n != nil ; n = n . NextSibling {
438
- visitNode (ctx , procs , n )
465
+ for n := node .FirstChild ; n != nil ; {
466
+ n = visitNode (ctx , procs , n )
439
467
}
440
468
}
441
- // ignore everything else
469
+ return node . NextSibling
442
470
}
443
471
444
472
// textNode runs the passed node through various processors, in order to handle
@@ -851,7 +879,7 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
851
879
852
880
// FIXME: the use of "mode" is quite dirty and hacky, for example: what is a "document"? how should it be rendered?
853
881
// The "mode" approach should be refactored to some other more clear&reliable way.
854
- crossLinkOnly := ( ctx .Metas ["mode" ] == "document" && ! ctx .IsWiki )
882
+ crossLinkOnly := ctx .Metas ["mode" ] == "document" && ! ctx .IsWiki
855
883
856
884
var (
857
885
found bool
0 commit comments