internal/frontend: rewrite img links to GitHub blobs
GitHub will translate a .../blob/... URL in a README to the
corresponding .../raw/... URL. We need to do the same.
Fixes golang/go#45168
Change-Id: Ib5b9a2c33d2b3da324f16f55790ee7b228f39d7f
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/303790
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/frontend/goldmark.go b/internal/frontend/goldmark.go
index c58dd0b..3ed3d2c 100644
--- a/internal/frontend/goldmark.go
+++ b/internal/frontend/goldmark.go
@@ -40,11 +40,11 @@
}
switch v := n.(type) {
case *ast.Image:
- if d := translateRelativeLink(string(v.Destination), g.info, true, g.readme); d != "" {
+ if d := translateLink(string(v.Destination), g.info, true, g.readme); d != "" {
v.Destination = []byte(d)
}
case *ast.Link:
- if d := translateRelativeLink(string(v.Destination), g.info, false, g.readme); d != "" {
+ if d := translateLink(string(v.Destination), g.info, false, g.readme); d != "" {
v.Destination = []byte(d)
}
}
diff --git a/internal/frontend/overview.go b/internal/frontend/overview.go
index c3144e6..14b9618 100644
--- a/internal/frontend/overview.go
+++ b/internal/frontend/overview.go
@@ -47,7 +47,7 @@
}
case blackfriday.Image, blackfriday.Link:
useRaw := node.Type == blackfriday.Image
- if d := translateRelativeLink(string(node.LinkData.Destination), mi.SourceInfo, useRaw, readme); d != "" {
+ if d := translateLink(string(node.LinkData.Destination), mi.SourceInfo, useRaw, readme); d != "" {
node.LinkData.Destination = []byte(d)
}
case blackfriday.HTMLBlock, blackfriday.HTMLSpan:
@@ -115,17 +115,37 @@
return ext == ".md" || ext == ".markdown"
}
-// translateRelativeLink converts relative image paths to absolute paths.
+// translateLink converts image links so that they will work on pkgsite.
//
// README files sometimes use relative image paths to image files inside the
// repository. As the discovery site doesn't host the full repository content,
// in order for the image to render, we need to convert the relative path to an
// absolute URL to a hosted image.
-func translateRelativeLink(dest string, info *source.Info, useRaw bool, readme *internal.Readme) string {
+//
+// In addition, GitHub will translate absolute non-raw links to image files to raw links.
+// For example, when GitHub renders a README with
+// <img src="https://github.com/gobuffalo/buffalo/blob/master/logo.svg">
+// it rewrites it to
+// <img src="https://github.com/gobuffalo/buffalo/raw/master/logo.svg">
+// (replacing "blob" with "raw").
+// We do that too.
+func translateLink(dest string, info *source.Info, useRaw bool, readme *internal.Readme) string {
destURL, err := url.Parse(dest)
- if err != nil || destURL.IsAbs() {
+ if err != nil {
return ""
}
+ if destURL.IsAbs() {
+ if destURL.Host != "github.com" {
+ return ""
+ }
+ parts := strings.Split(destURL.Path, "/")
+ if len(parts) < 4 || parts[3] != "blob" {
+ return ""
+ }
+ parts[3] = "raw"
+ destURL.Path = strings.Join(parts, "/")
+ return destURL.String()
+ }
if destURL.Path == "" {
// This is a fragment; leave it.
return "#readme-" + destURL.Fragment
@@ -195,7 +215,7 @@
var attrs []html.Attribute
for _, a := range n.Attr {
if a.Key == "src" {
- if v := translateRelativeLink(a.Val, info, true, readme); v != "" {
+ if v := translateLink(a.Val, info, true, readme); v != "" {
a.Val = v
changed = true
}
diff --git a/internal/frontend/overview_test.go b/internal/frontend/overview_test.go
index ce8e3ae..2cba4f5 100644
--- a/internal/frontend/overview_test.go
+++ b/internal/frontend/overview_test.go
@@ -213,6 +213,24 @@
},
want: `<p><a href="#readme-heading-id" rel="nofollow">Local Heading</a></p>`,
},
+ {
+ name: "absolute link to blob",
+ mi: aModule,
+ readme: &internal.Readme{
+ Filepath: "README.md",
+ Contents: `<img src="https://github.com/foo/bar/blob/master/logo.svg">`,
+ },
+ want: `<p><img src="https://github.com/foo/bar/raw/master/logo.svg"/></p>`,
+ },
+ {
+ name: "absolute link not to blob",
+ mi: aModule,
+ readme: &internal.Readme{
+ Filepath: "README.md",
+ Contents: `<img src="https://github.com/foo/bar/bloob/master/logo.svg">`,
+ },
+ want: `<p><img src="https://github.com/foo/bar/bloob/master/logo.svg"></p>`,
+ },
}
checkReadme := func(ctx context.Context, t *testing.T, mi *internal.ModuleInfo, readme *internal.Readme, want string) {
hgot, err := LegacyReadmeHTML(ctx, mi, readme)