Skip to content

Commit f6ee142

Browse files
authored
Opengraph sizes (#353)
Adding opengram img size selection
1 parent b9e6027 commit f6ee142

File tree

6 files changed

+213
-7
lines changed

6 files changed

+213
-7
lines changed

Diff for: go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ require (
4242
github.com/stretchr/testify v1.7.0 // indirect
4343
github.com/tdewolff/minify/v2 v2.12.0 // indirect
4444
golang.org/x/crypto v0.0.0-20220824171710-5757bc0c5503 // indirect
45-
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 // indirect
45+
golang.org/x/image v0.2.0 // indirect
4646
golang.org/x/sys v0.3.0 // indirect
4747
golang.org/x/term v0.3.0 // indirect
4848
gopkg.in/yaml.v2 v2.4.0 // indirect

Diff for: go.sum

+16
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,9 @@ github.com/tdewolff/parse/v2 v2.6.1 h1:RIfy1erADkO90ynJWvty8VIkqqKYRzf2iLp8ObG17
702702
github.com/tdewolff/parse/v2 v2.6.1/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
703703
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
704704
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
705+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
706+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
707+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
705708
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
706709
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
707710
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@@ -719,6 +722,11 @@ golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 h1:/eM0PCrQI2xd471rI+snWuu
719722
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
720723
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
721724
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
725+
golang.org/x/image v0.2.0 h1:/DcQ0w3VHKCC5p0/P2B0JpAZ9Z++V2KOo2fyU89CXBQ=
726+
golang.org/x/image v0.2.0/go.mod h1:la7oBXb9w3YFjBqaAwtynVioc1ZvOnNteUNrifGNmAI=
727+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
728+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
729+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
722730
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
723731
golang.org/x/net v0.0.0-20220615171555-694bf12d69de h1:ogOG2+P6LjO2j55AkRScrkB2BFpd+Z8TY2wcM0Z3MGo=
724732
golang.org/x/net v0.0.0-20220615171555-694bf12d69de/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@@ -800,6 +808,9 @@ golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk=
800808
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
801809
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
802810
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
811+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
812+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
813+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
803814
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
804815
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
805816
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -852,9 +863,14 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
852863
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
853864
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
854865
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
866+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
855867
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
856868
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
869+
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
857870
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
871+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
872+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
873+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
858874
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
859875
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
860876
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

Diff for: manipulations/opengraphimg/opengraphimg.go

+22-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ import (
2626
"golang.org/x/net/html"
2727
)
2828

29+
const (
30+
RECOMMENDED_OG_IMG_WIDTH = 1200
31+
)
32+
33+
var (
34+
genimgsLookupSizes = genimgs.LookupSizes
35+
)
36+
2937
func Manipulator(runtime manipulations.Runtime, doc *html.Node) error {
3038
els := htmlparsing.FindNodesByTag("meta", doc)
3139
for _, ele := range els {
@@ -49,20 +57,30 @@ func Manipulator(runtime manipulations.Runtime, doc *html.Node) error {
4957
continue
5058
}
5159

52-
imgs, err := genimgs.LookupSizes(runtime.S3, runtime.Config, c.Val)
60+
imgs, err := genimgsLookupSizes(runtime.S3, runtime.Config, c.Val)
5361
if err != nil {
5462
return err
5563
}
5664

5765
imgsByTypes := genimgs.GroupByType(imgs)
5866
imgsByType := imgsByTypes[""]
5967
if len(imgsByType) == 0 {
60-
return nil
68+
continue
6169
}
6270

63-
largestImg := imgsByType[len(imgsByType)-1]
71+
var img *genimgs.GenImg = nil
72+
for _, i := range imgs {
73+
if i.Size <= RECOMMENDED_OG_IMG_WIDTH {
74+
img = &i
75+
break
76+
}
77+
}
78+
79+
if img == nil {
80+
continue
81+
}
6482

65-
c.Val = fmt.Sprintf("%v%v", runtime.Config.BaseURL, largestImg.URL)
83+
c.Val = fmt.Sprintf("%v%v", runtime.Config.BaseURL, img.URL)
6684
attributes["content"] = c
6785
ele.Attr = htmlparsing.AttributesList(attributes)
6886
}

Diff for: manipulations/opengraphimg/opengraphimg_test.go

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package opengraphimg
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"os"
7+
"strings"
8+
"testing"
9+
10+
"github.com/aws/aws-sdk-go-v2/service/s3"
11+
"github.com/gauntface/go-html-asset-manager/v4/assets/genimgs"
12+
"github.com/gauntface/go-html-asset-manager/v4/manipulations"
13+
"github.com/gauntface/go-html-asset-manager/v4/utils/config"
14+
"github.com/gauntface/go-html-asset-manager/v4/utils/html/htmlparsing"
15+
"github.com/google/go-cmp/cmp"
16+
"golang.org/x/net/html"
17+
)
18+
19+
var errInjected = errors.New("injected error")
20+
21+
var reset func()
22+
23+
func TestMain(m *testing.M) {
24+
origGenimgsLookupSizes := genimgsLookupSizes
25+
26+
reset = func() {
27+
genimgsLookupSizes = origGenimgsLookupSizes
28+
}
29+
30+
os.Exit(m.Run())
31+
}
32+
33+
func TestManipulator(t *testing.T) {
34+
tests := []struct {
35+
description string
36+
doc *html.Node
37+
findNodes func(tag string, node *html.Node) []*html.Node
38+
genimgsLookupSizes func(s3 *s3.Client, conf *config.Config, imgPath string) ([]genimgs.GenImg, error)
39+
wantError error
40+
wantHTML string
41+
}{
42+
{
43+
description: "do nothing when no property",
44+
findNodes: htmlparsing.FindNodesByTag,
45+
doc: MustGetNode(t, `<meta diff-attr="og:image" />`),
46+
wantHTML: `<html><head><meta diff-attr="og:image"/></head><body></body></html>`,
47+
},
48+
{
49+
description: "do nothing when not og:image property",
50+
findNodes: htmlparsing.FindNodesByTag,
51+
doc: MustGetNode(t, `<meta property="og:other" />`),
52+
wantHTML: `<html><head><meta property="og:other"/></head><body></body></html>`,
53+
},
54+
{
55+
description: "do nothing when no content",
56+
findNodes: htmlparsing.FindNodesByTag,
57+
doc: MustGetNode(t, `<meta property="og:image" />`),
58+
wantHTML: `<html><head><meta property="og:image"/></head><body></body></html>`,
59+
},
60+
{
61+
description: "return error if getting images fails",
62+
findNodes: htmlparsing.FindNodesByTag,
63+
doc: MustGetNode(t, `<meta property="og:image" content="/images/default-social.png" />`),
64+
genimgsLookupSizes: func(s3 *s3.Client, conf *config.Config, imgPath string) ([]genimgs.GenImg, error) {
65+
return nil, errInjected
66+
},
67+
wantError: errInjected,
68+
},
69+
{
70+
description: "do nothing when no images",
71+
findNodes: htmlparsing.FindNodesByTag,
72+
doc: MustGetNode(t, `<meta property="og:image" content="/images/default-social.png" />`),
73+
genimgsLookupSizes: func(s3 *s3.Client, conf *config.Config, imgPath string) ([]genimgs.GenImg, error) {
74+
return []genimgs.GenImg{}, nil
75+
},
76+
wantHTML: `<html><head><meta property="og:image" content="/images/default-social.png"/></head><body></body></html>`,
77+
},
78+
{
79+
description: "do nothing when no basic images",
80+
findNodes: htmlparsing.FindNodesByTag,
81+
doc: MustGetNode(t, `<meta property="og:image" content="/images/default-social.png" />`),
82+
genimgsLookupSizes: func(s3 *s3.Client, conf *config.Config, imgPath string) ([]genimgs.GenImg, error) {
83+
return []genimgs.GenImg{
84+
{
85+
Type: "image/webp",
86+
},
87+
}, nil
88+
},
89+
wantHTML: `<html><head><meta property="og:image" content="/images/default-social.png"/></head><body></body></html>`,
90+
},
91+
{
92+
description: "do nothing when no images on the right size",
93+
findNodes: htmlparsing.FindNodesByTag,
94+
doc: MustGetNode(t, `<meta property="og:image" content="/images/default-social.png" />`),
95+
genimgsLookupSizes: func(s3 *s3.Client, conf *config.Config, imgPath string) ([]genimgs.GenImg, error) {
96+
return []genimgs.GenImg{
97+
{
98+
Size: RECOMMENDED_OG_IMG_WIDTH + 1,
99+
},
100+
}, nil
101+
},
102+
wantHTML: `<html><head><meta property="og:image" content="/images/default-social.png"/></head><body></body></html>`,
103+
},
104+
{
105+
description: "update the image with the correct size",
106+
findNodes: htmlparsing.FindNodesByTag,
107+
doc: MustGetNode(t, `<meta property="og:image" content="/images/default-social.png" />`),
108+
genimgsLookupSizes: func(s3 *s3.Client, conf *config.Config, imgPath string) ([]genimgs.GenImg, error) {
109+
return []genimgs.GenImg{
110+
{
111+
Size: RECOMMENDED_OG_IMG_WIDTH,
112+
URL: "/images/default-social.1200xabc.png",
113+
},
114+
}, nil
115+
},
116+
wantHTML: `<html><head><meta content="http://base-url.com/images/default-social.1200xabc.png" property="og:image"/></head><body></body></html>`,
117+
},
118+
}
119+
120+
for _, tt := range tests {
121+
t.Run(tt.description, func(t *testing.T) {
122+
defer reset()
123+
124+
genimgsLookupSizes = tt.genimgsLookupSizes
125+
126+
r := manipulations.Runtime{
127+
Config: &config.Config{
128+
BaseURL: "http://base-url.com",
129+
},
130+
}
131+
132+
err := Manipulator(r, tt.doc)
133+
if !errors.Is(err, tt.wantError) {
134+
t.Fatalf("Unexpected error; got %v, want %v", err, tt.wantError)
135+
}
136+
137+
if err != nil {
138+
return
139+
}
140+
141+
if diff := cmp.Diff(MustRenderNode(t, tt.doc), tt.wantHTML); diff != "" {
142+
t.Fatalf("Unexpected HTML files; diff %v", diff)
143+
}
144+
})
145+
}
146+
}
147+
148+
func MustGetNode(t *testing.T, input string) *html.Node {
149+
t.Helper()
150+
151+
doc, err := html.Parse(strings.NewReader(input))
152+
if err != nil {
153+
t.Fatalf("Failed to parse HTML: %v", err)
154+
}
155+
return doc
156+
}
157+
158+
func MustRenderNode(t *testing.T, n *html.Node) string {
159+
t.Helper()
160+
161+
if n == nil {
162+
return ""
163+
}
164+
165+
var buf bytes.Buffer
166+
err := html.Render(&buf, n)
167+
if err != nil {
168+
t.Fatalf("failed to render html node to string: %v", err)
169+
}
170+
171+
return buf.String()
172+
}

Diff for: package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"devDependencies": {
3-
"@gauntface/logger": "3.0.63"
3+
"@gauntface/logger": "^3.0.63"
44
},
55
"dependencies": {
66
"avif": "0.4.0"

0 commit comments

Comments
 (0)