@quintype/seo 1.42.0 → 1.42.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.42.1](https://github.com/quintype/quintype-node-seo/compare/v1.42.0...v1.42.1) (2023-04-06)
6
+
7
+ ## [1.42.0](https://github.com/quintype/quintype-node-seo/compare/v1.40.10...v1.42.0) (2023-04-06)
8
+
9
+
10
+ ### Features
11
+
12
+ * **canonical:** Add canonical url toggle ([#539](https://github.com/quintype/quintype-node-seo/issues/539)) ([3c18124](https://github.com/quintype/quintype-node-seo/commit/3c181249b7adb06061a8a4c16aa71b640b21679c))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **canonical:** Toggle canonical tags ([1f8a4fe](https://github.com/quintype/quintype-node-seo/commit/1f8a4fe0955688080095275290dabe79dc6344d6))
18
+ * **dates:** update datePublished ([#537](https://github.com/quintype/quintype-node-seo/issues/537)) ([b81f1ae](https://github.com/quintype/quintype-node-seo/commit/b81f1aeef63937673f376203a8d7a45b7a0de2b3))
19
+ * **discover-meta:** Add max image meta tag to story pages ([e96fa17](https://github.com/quintype/quintype-node-seo/commit/e96fa17637e2a625aa39601d2ace8ad2ea46d786))
20
+ * **live-blog:** Support articleBody in BlogPosting schema ([#532](https://github.com/quintype/quintype-node-seo/issues/532)) ([4389509](https://github.com/quintype/quintype-node-seo/commit/43895094aa2d7c1cafb347a539ad70a16b06727e))
21
+
5
22
  ## [1.42.0](https://github.com/quintype/quintype-node-seo/compare/v1.40.13...v1.42.0) (2023-04-03)
6
23
 
7
24
 
package/dist/index.cjs.js CHANGED
@@ -6,8 +6,8 @@ var lodash = require('lodash');
6
6
  var React = require('react');
7
7
  var ReactDomServer = require('react-dom/server');
8
8
  var get = require('lodash/get');
9
- var url = require('url');
10
9
  var dateFnsTz = require('date-fns-tz');
10
+ var url = require('url');
11
11
  var isUndefined = require('lodash/isUndefined');
12
12
  var omitBy = require('lodash/omitBy');
13
13
  var quintypeJs = require('quintype-js');
@@ -25,7 +25,7 @@ function objectToTags(object) {
25
25
  }
26
26
 
27
27
  function getPropertyName(key) {
28
- return key.startsWith('fb:') || key.startsWith('og:') ? 'property' : 'name';
28
+ return key.startsWith("fb:") || key.startsWith("og:") ? "property" : "name";
29
29
  }
30
30
 
31
31
  function stripMillisecondsFromTime(date, timezone) {
@@ -33,20 +33,28 @@ function stripMillisecondsFromTime(date, timezone) {
33
33
  if (!toReturn) return toReturn;
34
34
  const zonedTime = timezone && dateFnsTz.utcToZonedTime(date, timezone);
35
35
  const formatZonedTime = zonedTime && dateFnsTz.format(zonedTime, "yyyy-MM-dd'T'HH:mm:ssXXX", { timeZone: timezone });
36
- const formatToReturn = toReturn.split('.')[0] + "Z";
36
+ const formatToReturn = toReturn.split(".")[0] + "Z";
37
37
  return timezone ? formatZonedTime : formatToReturn;
38
38
  }
39
39
 
40
40
  function getQueryParams(url$1) {
41
41
  const urlObj = new url.URL(url$1);
42
42
  const search_params = new url.URLSearchParams(urlObj.search);
43
- const getWidth = search_params.get('w') || '';
44
- const getHeight = search_params.get('h') || '';
43
+ const getWidth = search_params.get("w") || "";
44
+ const getHeight = search_params.get("h") || "";
45
45
  return { width: getWidth, height: getHeight };
46
46
  }
47
47
 
48
48
  function isStoryPublic(story) {
49
- return story.access === undefined || story.access === null || story.access === 'public';
49
+ return story.access === undefined || story.access === null || story.access === "public";
50
+ }
51
+
52
+ function getWatermarkImage(story, cdnSrc, cdnURL) {
53
+ const watermarkImageS3Key = lodash.get(story, ["watermark", "social", "image-s3-key"], "");
54
+ if (cdnSrc && cdnSrc.includes("gumlet") && watermarkImageS3Key.length > 0) {
55
+ return `https://${cdnURL}/${watermarkImageS3Key}`;
56
+ }
57
+ return watermarkImageS3Key;
50
58
  }
51
59
 
52
60
  function showAmpTag({ ampStoryPages = true }, pageType, story) {
@@ -320,6 +328,14 @@ function pickImage({ pageType, config, seoConfig, data, url }) {
320
328
  */
321
329
  function ImageTags(seoConfig, config, pageType, data, { url = {} }) {
322
330
  const { image, alt, includesHost = false } = pickImage({ pageType, data, url, seoConfig, config });
331
+ const dataObj = lodash.get(data, ["data"], {});
332
+ const story = lodash.get(dataObj, ["story"], {});
333
+ const publisherConfig = lodash.get(data, ["config", "publisher-attributes"], {});
334
+ const fallbackValue = dataObj.hasOwnProperty("collection") ? true : false;
335
+ const isWatermarkDisabled = lodash.get(story, ["metadata", "watermark-image", "disabled"], fallbackValue);
336
+ const imageCdnSrc = publisherConfig.cdn_src;
337
+ const imageCdnUrl = publisherConfig.cdn_image || config["cdn-image"];
338
+ const fallbackSocialImage = lodash.get(seoConfig, ["fallbackSocialImage"]);
323
339
 
324
340
  if (!image) {
325
341
  return [];
@@ -330,16 +346,52 @@ function ImageTags(seoConfig, config, pageType, data, { url = {} }) {
330
346
  if (pageType == "story-page") {
331
347
  tags.push({ name: "robots", content: "max-image-preview:large" });
332
348
  }
349
+ const getHeroImage = (imageRatio, imageProp) => {
350
+ return includesHost ? image : `https://${imageCdnUrl}/${image.path(imageRatio, imageProp)}`;
351
+ };
352
+
353
+ const getWatermarkHeroImage = (imageRatio, imageProp) => {
354
+ const overlayWatermarkProps = Object.assign({}, imageProp, {
355
+ overlay: getWatermarkImage(story, imageCdnSrc, imageCdnUrl),
356
+ overlay_position: "bottom"
357
+ });
358
+
359
+ const watermarkImageProps = imageCdnSrc && imageCdnSrc.includes("gumlet") ? Object.assign({}, overlayWatermarkProps, {
360
+ overlay_width_pct: 1
361
+ }) : Object.assign({}, overlayWatermarkProps, {
362
+ overlay_width: 100
363
+ });
364
+
365
+ const getFallbackImage = () => {
366
+ if (fallbackSocialImage) {
367
+ const fbUrl = new URL(fallbackSocialImage);
368
+ const fbImageSlug = new quintypeJs.FocusedImage(fbUrl.href.slice(fbUrl.origin.length + 1));
369
+ const fbHost = new URL(fallbackSocialImage).origin;
370
+ return `${fbHost}/${fbImageSlug.path(imageRatio, watermarkImageProps)}`;
371
+ } else {
372
+ return image;
373
+ }
374
+ };
375
+
376
+ return includesHost ? getFallbackImage() : `https://${imageCdnUrl}/${image.path(imageRatio, watermarkImageProps)}`;
377
+ };
378
+
379
+ const getImageContent = imageRatio => {
380
+ const imageProp = {
381
+ w: 1200,
382
+ ar: imageRatio.join(":"),
383
+ auto: "format,compress",
384
+ ogImage: true,
385
+ mode: "crop",
386
+ enlarge: true
387
+ };
388
+ return isWatermarkDisabled ? getHeroImage(imageRatio, imageProp) : getWatermarkHeroImage(imageRatio, imageProp);
389
+ };
333
390
 
334
391
  if (seoConfig.enableTwitterCards) {
335
392
  tags.push({
336
393
  name: "twitter:image",
337
- content: includesHost ? image : `https://${config["cdn-image"]}/${image.path([16, 9], {
338
- w: 1200,
339
- auto: "format,compress",
340
- ogImage: true,
341
- enlarge: true
342
- })}`
394
+ content: getImageContent([40, 21])
343
395
  });
344
396
  alt && tags.push({ property: "twitter:image:alt", content: alt });
345
397
  }
@@ -347,12 +399,7 @@ function ImageTags(seoConfig, config, pageType, data, { url = {} }) {
347
399
  if (seoConfig.enableOgTags) {
348
400
  tags.push({
349
401
  property: "og:image",
350
- content: includesHost ? image : `https://${config["cdn-image"]}/${image.path([40, 21], {
351
- w: 1200,
352
- auto: "format,compress",
353
- ogImage: true,
354
- enlarge: true
355
- })}`
402
+ content: getImageContent([40, 21])
356
403
  });
357
404
  tags.push({ property: "og:image:width", content: 1200 });
358
405
  if (lodash.get(image, ["metadata", "focus-point"])) {
@@ -587,6 +634,7 @@ function generateArticleData(structuredData = {}, story = {}, publisherConfig =
587
634
  function generateArticleImageData(image, publisherConfig = {}) {
588
635
  const imageWidth = 1200;
589
636
  const imageHeight = 675;
637
+
590
638
  const articleImage = imageUrl(publisherConfig, image, imageWidth, imageHeight);
591
639
 
592
640
  return Object.assign({}, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quintype/seo",
3
- "version": "1.42.0",
3
+ "version": "1.42.1",
4
4
  "description": "SEO Modules for Quintype",
5
5
  "main": "dist/index.cjs.js",
6
6
  "repository": "https://github.com/quintype/quintype-node-seo",
package/src/image-tags.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { get, isEmpty } from "lodash";
2
2
  import { FocusedImage } from "quintype-js";
3
+ import { getWatermarkImage } from "./utils";
3
4
 
4
5
  function pickImageFromCard(story, cardId) {
5
6
  const { metadata = {} } = story.cards.find((card) => card.id === cardId) || {};
@@ -112,6 +113,14 @@ function pickImage({ pageType, config, seoConfig, data, url }) {
112
113
  */
113
114
  export function ImageTags(seoConfig, config, pageType, data, { url = {} }) {
114
115
  const { image, alt, includesHost = false } = pickImage({ pageType, data, url, seoConfig, config });
116
+ const dataObj = get(data, ["data"], {});
117
+ const story = get(dataObj, ["story"], {});
118
+ const publisherConfig = get(data, ["config", "publisher-attributes"], {});
119
+ const fallbackValue = dataObj.hasOwnProperty("collection") ? true : false;
120
+ const isWatermarkDisabled = get(story, ["metadata", "watermark-image", "disabled"], fallbackValue);
121
+ const imageCdnSrc = publisherConfig.cdn_src;
122
+ const imageCdnUrl = publisherConfig.cdn_image || config["cdn-image"];
123
+ const fallbackSocialImage = get(seoConfig, ["fallbackSocialImage"]);
115
124
 
116
125
  if (!image) {
117
126
  return [];
@@ -122,18 +131,55 @@ export function ImageTags(seoConfig, config, pageType, data, { url = {} }) {
122
131
  if (pageType == "story-page") {
123
132
  tags.push({ name: "robots", content: "max-image-preview:large" });
124
133
  }
134
+ const getHeroImage = (imageRatio, imageProp) => {
135
+ return includesHost ? image : `https://${imageCdnUrl}/${image.path(imageRatio, imageProp)}`;
136
+ };
137
+
138
+ const getWatermarkHeroImage = (imageRatio, imageProp) => {
139
+ const overlayWatermarkProps = Object.assign({}, imageProp, {
140
+ overlay: getWatermarkImage(story, imageCdnSrc, imageCdnUrl),
141
+ overlay_position: "bottom",
142
+ });
143
+
144
+ const watermarkImageProps =
145
+ imageCdnSrc && imageCdnSrc.includes("gumlet")
146
+ ? Object.assign({}, overlayWatermarkProps, {
147
+ overlay_width_pct: 1,
148
+ })
149
+ : Object.assign({}, overlayWatermarkProps, {
150
+ overlay_width: 100,
151
+ });
152
+
153
+ const getFallbackImage = () => {
154
+ if (fallbackSocialImage) {
155
+ const fbUrl = new URL(fallbackSocialImage);
156
+ const fbImageSlug = new FocusedImage(fbUrl.href.slice(fbUrl.origin.length + 1));
157
+ const fbHost = new URL(fallbackSocialImage).origin;
158
+ return `${fbHost}/${fbImageSlug.path(imageRatio, watermarkImageProps)}`;
159
+ } else {
160
+ return image;
161
+ }
162
+ };
163
+
164
+ return includesHost ? getFallbackImage() : `https://${imageCdnUrl}/${image.path(imageRatio, watermarkImageProps)}`;
165
+ };
166
+
167
+ const getImageContent = (imageRatio) => {
168
+ const imageProp = {
169
+ w: 1200,
170
+ ar: imageRatio.join(":"),
171
+ auto: "format,compress",
172
+ ogImage: true,
173
+ mode: "crop",
174
+ enlarge: true,
175
+ };
176
+ return isWatermarkDisabled ? getHeroImage(imageRatio, imageProp) : getWatermarkHeroImage(imageRatio, imageProp);
177
+ };
125
178
 
126
179
  if (seoConfig.enableTwitterCards) {
127
180
  tags.push({
128
181
  name: "twitter:image",
129
- content: includesHost
130
- ? image
131
- : `https://${config["cdn-image"]}/${image.path([16, 9], {
132
- w: 1200,
133
- auto: "format,compress",
134
- ogImage: true,
135
- enlarge: true,
136
- })}`,
182
+ content: getImageContent([40, 21]),
137
183
  });
138
184
  alt && tags.push({ property: "twitter:image:alt", content: alt });
139
185
  }
@@ -141,14 +187,7 @@ export function ImageTags(seoConfig, config, pageType, data, { url = {} }) {
141
187
  if (seoConfig.enableOgTags) {
142
188
  tags.push({
143
189
  property: "og:image",
144
- content: includesHost
145
- ? image
146
- : `https://${config["cdn-image"]}/${image.path([40, 21], {
147
- w: 1200,
148
- auto: "format,compress",
149
- ogImage: true,
150
- enlarge: true,
151
- })}`,
190
+ content: getImageContent([40, 21]),
152
191
  });
153
192
  tags.push({ property: "og:image:width", content: 1200 });
154
193
  if (get(image, ["metadata", "focus-point"])) {
@@ -129,6 +129,7 @@ function generateArticleData(structuredData = {}, story = {}, publisherConfig =
129
129
  function generateArticleImageData(image, publisherConfig = {}) {
130
130
  const imageWidth = 1200;
131
131
  const imageHeight = 675;
132
+
132
133
  const articleImage = imageUrl(publisherConfig, image, imageWidth, imageHeight);
133
134
 
134
135
  return Object.assign(
package/src/utils.js CHANGED
@@ -1,35 +1,42 @@
1
- import {entries} from 'lodash';
2
- import { URL, URLSearchParams } from 'url';
3
- import { format, utcToZonedTime } from 'date-fns-tz';
1
+ import { format, utcToZonedTime } from "date-fns-tz";
2
+ import { entries, get } from "lodash";
3
+ import { URL, URLSearchParams } from "url";
4
4
 
5
5
  export function objectToTags(object) {
6
6
  return entries(object)
7
7
  .filter(([key, value]) => value)
8
- .map(([key, value]) => ({[getPropertyName(key)]: key, content: value}));
8
+ .map(([key, value]) => ({ [getPropertyName(key)]: key, content: value }));
9
9
  }
10
10
 
11
11
  function getPropertyName(key) {
12
- return (key.startsWith('fb:') || key.startsWith('og:')) ? 'property' : 'name';
12
+ return key.startsWith("fb:") || key.startsWith("og:") ? "property" : "name";
13
13
  }
14
14
 
15
15
  export function stripMillisecondsFromTime(date, timezone) {
16
16
  const toReturn = date.toJSON();
17
- if(!toReturn)
18
- return toReturn
17
+ if (!toReturn) return toReturn;
19
18
  const zonedTime = timezone && utcToZonedTime(date, timezone);
20
19
  const formatZonedTime = zonedTime && format(zonedTime, "yyyy-MM-dd'T'HH:mm:ssXXX", { timeZone: timezone });
21
- const formatToReturn = toReturn.split('.')[0]+"Z";
20
+ const formatToReturn = toReturn.split(".")[0] + "Z";
22
21
  return timezone ? formatZonedTime : formatToReturn;
23
22
  }
24
23
 
25
24
  export function getQueryParams(url) {
26
- const urlObj = new URL(url);
25
+ const urlObj = new URL(url);
27
26
  const search_params = new URLSearchParams(urlObj.search);
28
- const getWidth = search_params.get('w') || '';
29
- const getHeight = search_params.get('h') || '';
30
- return {width: getWidth, height: getHeight};
27
+ const getWidth = search_params.get("w") || "";
28
+ const getHeight = search_params.get("h") || "";
29
+ return { width: getWidth, height: getHeight };
31
30
  }
32
31
 
33
32
  export function isStoryPublic(story) {
34
- return story.access === undefined || story.access === null || story.access === 'public';
33
+ return story.access === undefined || story.access === null || story.access === "public";
34
+ }
35
+
36
+ export function getWatermarkImage(story, cdnSrc, cdnURL) {
37
+ const watermarkImageS3Key = get(story, ["watermark", "social", "image-s3-key"], "");
38
+ if (cdnSrc && cdnSrc.includes("gumlet") && watermarkImageS3Key.length > 0) {
39
+ return `https://${cdnURL}/${watermarkImageS3Key}`;
40
+ }
41
+ return watermarkImageS3Key;
35
42
  }
@@ -17,6 +17,16 @@ describe("ImageTags", function () {
17
17
  it("gets the twitter tags", function () {
18
18
  const story = {
19
19
  "hero-image-s3-key": "my/image.png",
20
+ metadata: {
21
+ "watermark-image": {
22
+ disabled: true,
23
+ },
24
+ },
25
+ watermark: {
26
+ social: {
27
+ "image-s3-key": "my/watermark-image.png",
28
+ },
29
+ },
20
30
  alternative: {
21
31
  social: {
22
32
  default: {
@@ -39,11 +49,55 @@ describe("ImageTags", function () {
39
49
  const string = getSeoMetadata(seoConfig, config, "story-page", { data: { story: story } }, {});
40
50
  const ampPageString = getSeoMetadata(seoConfig, config, "story-page-amp", { data: { story: story } }, {});
41
51
  assertContains(
42
- '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?w=1200&amp;auto=format%2Ccompress&amp;ogImage=true&amp;enlarge=true"/>',
52
+ '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true"/>',
43
53
  string
44
54
  );
45
55
  assertContains(
46
- '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?w=1200&amp;auto=format%2Ccompress&amp;ogImage=true&amp;enlarge=true"/>',
56
+ '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true"/>',
57
+ ampPageString
58
+ );
59
+ });
60
+
61
+ it("gets the twitter tags with watermark", function () {
62
+ const story = {
63
+ "hero-image-s3-key": "my/image.png",
64
+ metadata: {
65
+ "watermark-image": {
66
+ disabled: false,
67
+ },
68
+ },
69
+ watermark: {
70
+ social: {
71
+ "image-s3-key": "my/watermark-image.png",
72
+ },
73
+ },
74
+ alternative: {
75
+ social: {
76
+ default: {
77
+ headline: null,
78
+ "hero-image": {
79
+ "hero-image-s3-key": "my/socialimage.png",
80
+ },
81
+ },
82
+ },
83
+ home: {
84
+ default: {
85
+ headline: null,
86
+ "hero-image": {
87
+ "hero-image-s3-key": "my/homeimage.png",
88
+ },
89
+ },
90
+ },
91
+ },
92
+ };
93
+ const string = getSeoMetadata(seoConfig, config, "story-page", { data: { story: story } }, {});
94
+ const ampPageString = getSeoMetadata(seoConfig, config, "story-page-amp", { data: { story: story } }, {});
95
+ assertContains(
96
+ '<meta property="og:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true&amp;overlay=my%2Fwatermark-image.png&amp;overlay_position=bottom&amp;overlay_width=100"/>',
97
+ string
98
+ );
99
+ assertContains(
100
+ '<meta property="og:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true&amp;overlay=my%2Fwatermark-image.png&amp;overlay_position=bottom&amp;overlay_width=100"/>',
47
101
  ampPageString
48
102
  );
49
103
  });
@@ -78,6 +132,11 @@ describe("ImageTags", function () {
78
132
  it("has facebook tags resized correctly", function () {
79
133
  const story = {
80
134
  "hero-image-s3-key": "my/images.png",
135
+ metadata: {
136
+ "watermark-image": {
137
+ disabled: true,
138
+ },
139
+ },
81
140
  "hero-image-metadata": {
82
141
  width: 2400,
83
142
  height: 1260,
@@ -115,11 +174,11 @@ describe("ImageTags", function () {
115
174
  const string = getSeoMetadata(seoConfig, config, "story-page", { data: { story: story } }, {});
116
175
  const ampPageString = getSeoMetadata(seoConfig, config, "story-page-amp", { data: { story: story } }, {});
117
176
  assertContains(
118
- '<meta property="og:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?rect=0%2C0%2C2400%2C1260&amp;w=1200&amp;auto=format%2Ccompress&amp;ogImage=true&amp;enlarge=true"/>',
177
+ '<meta property="og:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?rect=0%2C0%2C2400%2C1260&amp;w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true"/>',
119
178
  string
120
179
  );
121
180
  assertContains(
122
- '<meta property="og:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?rect=0%2C0%2C2400%2C1260&amp;w=1200&amp;auto=format%2Ccompress&amp;ogImage=true&amp;enlarge=true"/>',
181
+ '<meta property="og:image" content="https://thumbor.assettype.com/my%2Fsocialimage.png?rect=0%2C0%2C2400%2C1260&amp;w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true"/>',
123
182
  ampPageString
124
183
  );
125
184
  assertContains('<meta property="og:image:width" content="1200"/>', string);
@@ -131,6 +190,11 @@ describe("ImageTags", function () {
131
190
  it("gets card image values instead of story image values on card share", function () {
132
191
  const story = {
133
192
  "hero-image-s3-key": "my/image.png",
193
+ metadata: {
194
+ "watermark-image": {
195
+ disabled: true,
196
+ },
197
+ },
134
198
  cards: [
135
199
  {
136
200
  id: "sample-card-id",
@@ -163,7 +227,7 @@ describe("ImageTags", function () {
163
227
  const string = getSeoMetadata(seoConfig, config, "story-page", { data: { story: story } }, opts);
164
228
 
165
229
  assertContains(
166
- '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fcard%2Fimage.jpg?w=1200&amp;auto=format%2Ccompress&amp;ogImage=true&amp;enlarge=true"/>',
230
+ '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fcard%2Fimage.jpg?w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true"/>',
167
231
  string
168
232
  );
169
233
  });
@@ -318,6 +382,11 @@ describe("ImageTags", function () {
318
382
  it("gets story data as fallback if the card metadata is falsy", function () {
319
383
  const story = {
320
384
  "hero-image-s3-key": "my/image.png",
385
+ metadata: {
386
+ "watermark-image": {
387
+ disabled: true,
388
+ },
389
+ },
321
390
  cards: [
322
391
  {
323
392
  id: "sample-card-id",
@@ -343,11 +412,11 @@ describe("ImageTags", function () {
343
412
  const ampPageString = getSeoMetadata(seoConfig, config, "story-page-amp", { data: { story: story } }, opts);
344
413
 
345
414
  assertContains(
346
- '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fimage.png?w=1200&amp;auto=format%2Ccompress&amp;ogImage=true&amp;enlarge=true"/>',
415
+ '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fimage.png?w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true"/>',
347
416
  string
348
417
  );
349
418
  assertContains(
350
- '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fimage.png?w=1200&amp;auto=format%2Ccompress&amp;ogImage=true&amp;enlarge=true"/>',
419
+ '<meta name="twitter:image" content="https://thumbor.assettype.com/my%2Fimage.png?w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true"/>',
351
420
  ampPageString
352
421
  );
353
422
  });
@@ -368,7 +437,7 @@ describe("ImageTags", function () {
368
437
  };
369
438
  const string = getSeoMetadata(seoConfig, config, "home-page", { data: { collection: collection } }, {});
370
439
  assertContains(
371
- '<meta property="og:image" content="https://thumbor.assettype.com/my%2Fimage.png?rect=0%2C0%2C2400%2C1260&amp;w=1200&amp;auto=format%2Ccompress&amp;ogImage=true&amp;enlarge=true"/>',
440
+ '<meta property="og:image" content="https://thumbor.assettype.com/my%2Fimage.png?rect=0%2C0%2C2400%2C1260&amp;w=1200&amp;ar=40%3A21&amp;auto=format%2Ccompress&amp;ogImage=true&amp;mode=crop&amp;enlarge=true"/>',
372
441
  string
373
442
  );
374
443
  assertContains('<meta property="og:image:width" content="1200"/>', string);