Skip to content

Commit fe29c01

Browse files
wardpeetveryspryTylerBarnes
authored
feat(gatsby-source-wordpress): enable image-cdn (#34832)
Co-authored-by: Matt Ehlinger <[email protected]> Co-authored-by: veryspry <[email protected]> Co-authored-by: Tyler Barnes <[email protected]>
1 parent 46fe418 commit fe29c01

File tree

18 files changed

+388
-145
lines changed

18 files changed

+388
-145
lines changed

integration-tests/gatsby-source-wordpress/__tests__/__snapshots__/index.js.snap

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3915,6 +3915,13 @@ Array [
39153915
"parent",
39163916
"children",
39173917
"internal",
3918+
"filename",
3919+
"filesize",
3920+
"width",
3921+
"height",
3922+
"publicUrl",
3923+
"resize",
3924+
"gatsbyImageData",
39183925
],
39193926
"name": "WpMediaItem",
39203927
},

integration-tests/gatsby-source-wordpress/__tests__/index.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ describe(`[gatsby-source-wordpress] Run tests on develop build`, () => {
6060
let gatsbyDevelopProcess
6161

6262
beforeAll(async () => {
63+
if (process.env.SKIP_BEFORE_ALL) {
64+
return
65+
}
66+
6367
if (!isWarmCache) {
6468
await gatsbyCleanBeforeAll()
6569
}
@@ -105,7 +109,10 @@ describe(`[gatsby-source-wordpress] Run tests on develop build`, () => {
105109
require(`../test-fns/index`)
106110

107111
afterAll(done => {
108-
gatsbyDevelopProcess.kill()
112+
if (gatsbyDevelopProcess) {
113+
gatsbyDevelopProcess.kill()
114+
}
115+
109116
done()
110117
})
111118
})

integration-tests/gatsby-source-wordpress/docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ version: "3.2"
22

33
services:
44
db:
5+
platform: linux/x86_64
56
image: mysql:8
67
environment:
78
MYSQL_ROOT_PASSWORD: gtsb-wp-dckr

integration-tests/gatsby-source-wordpress/test-fns/data-resolution.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,4 +531,44 @@ describe(`data resolution`, () => {
531531
expect(wpMediaItem).toBeNull()
532532
}
533533
})
534+
535+
it(`Resolves Gatsby Image CDN data`, async () => {
536+
const {
537+
data: { allWpPost },
538+
} = await fetchGraphql({
539+
url,
540+
query: /* GraphQL */ `
541+
query {
542+
allWpPost {
543+
nodes {
544+
featuredImage {
545+
node {
546+
mediaItemUrl
547+
resize(width: 100, height: 100, quality: 100) {
548+
width
549+
height
550+
src
551+
}
552+
}
553+
}
554+
}
555+
}
556+
}
557+
`,
558+
})
559+
560+
allWpPost.nodes.forEach(node => {
561+
if (!node.featuredImage?.node) {
562+
return
563+
}
564+
565+
const { resize } = node.featuredImage.node
566+
const [, , , sourceUrl64, _args64, filename] = resize.src.split(`/`)
567+
568+
const sourceUrl = Buffer.from(sourceUrl64, `base64`).toString(`ascii`)
569+
570+
expect(node.featuredImage.node.mediaItemUrl).toEqual(sourceUrl)
571+
expect(node.featuredImage.node.mediaItemUrl).toContain(filename)
572+
})
573+
})
534574
})
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
export const referencedMediaItems = [
2+
{
3+
"id": `cG9zdDoxMTU=`,
4+
"mediaDetails": {
5+
"file": `2022/02/sasha-set-GURzQwO8Li0-unsplash-scaled.jpg`,
6+
"height": 1920,
7+
"sizes": [
8+
{
9+
"file": `sasha-set-GURzQwO8Li0-unsplash-300x225.jpg`,
10+
"fileSize": 18876,
11+
"height": `225`,
12+
"mimeType": `image/jpeg`,
13+
"name": `medium`,
14+
"sourceUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-300x225.jpg`,
15+
"width": `300`
16+
},
17+
{
18+
"file": `sasha-set-GURzQwO8Li0-unsplash-1024x768.jpg`,
19+
"fileSize": 214590,
20+
"height": `768`,
21+
"mimeType": `image/jpeg`,
22+
"name": `large`,
23+
"sourceUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-1024x768.jpg`,
24+
"width": `1024`
25+
},
26+
{
27+
"file": `sasha-set-GURzQwO8Li0-unsplash-150x150.jpg`,
28+
"fileSize": 7088,
29+
"height": `150`,
30+
"mimeType": `image/jpeg`,
31+
"name": `thumbnail`,
32+
"sourceUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-150x150.jpg`,
33+
"width": `150`
34+
},
35+
{
36+
"file": `sasha-set-GURzQwO8Li0-unsplash-768x576.jpg`,
37+
"fileSize": 118086,
38+
"height": `576`,
39+
"mimeType": `image/jpeg`,
40+
"name": `medium_large`,
41+
"sourceUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-768x576.jpg`,
42+
"width": `768`
43+
},
44+
{
45+
"file": `sasha-set-GURzQwO8Li0-unsplash-1536x1152.jpg`,
46+
"fileSize": 490613,
47+
"height": `1152`,
48+
"mimeType": `image/jpeg`,
49+
"name": `1536x1536`,
50+
"sourceUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-1536x1152.jpg`,
51+
"width": `1536`
52+
},
53+
{
54+
"file": `sasha-set-GURzQwO8Li0-unsplash-2048x1536.jpg`,
55+
"fileSize": 858627,
56+
"height": `1536`,
57+
"mimeType": `image/jpeg`,
58+
"name": `2048x2048`,
59+
"sourceUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-2048x1536.jpg`,
60+
"width": `2048`
61+
}
62+
],
63+
"width": 2560
64+
},
65+
"mediaItemUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-scaled.jpg`,
66+
"mediaType": `image`,
67+
"mimeType": `image/jpeg`,
68+
"sourceUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-scaled.jpg`,
69+
"srcSet": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-300x225.jpg 300w, http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-1024x768.jpg 1024w, http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-768x576.jpg 768w, http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-1536x1152.jpg 1536w, http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-2048x1536.jpg 2048w`,
70+
"width": 2560,
71+
"height": 1920,
72+
"placeholderUrl": `http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-300x225.jpg`,
73+
"internal": {
74+
"contentDigest": `5fa24d43c7fc603f9016933ad6bb3ee4`,
75+
}
76+
}
77+
]

packages/gatsby-source-wordpress/__tests__/process-node.test.js

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import execall from "execall"
22

3+
import { replaceNodeHtmlImages } from "../dist/steps/source-nodes/create-nodes/process-node"
4+
35
import {
46
getImgSrcRemoteFileMatchesFromNodeString,
5-
getImgTagMatchesWithUrl,
7+
getImgTagMatches,
68
getWpLinkRegex,
79
searchAndReplaceNodeStrings,
810
} from "../dist/steps/source-nodes/create-nodes/process-node"
@@ -20,7 +22,7 @@ test(`HTML image transformation regex matches images`, async () => {
2022

2123
expect(matches.length).toBe(3)
2224

23-
const imgTagMatches = getImgTagMatchesWithUrl({
25+
const imgTagMatches = getImgTagMatches({
2426
nodeString,
2527
wpUrl: `https://${wpUrl}`,
2628
})
@@ -69,3 +71,68 @@ test(`Search and replace node strings using regex matches`, async () => {
6971
7072
We need to test some <a href=\\"https://new-site.com/hi\\" />link</a> as well!`)
7173
})
74+
75+
jest.mock(`../dist/steps/source-nodes/fetch-nodes/fetch-referenced-media-items.js`, () => {
76+
return {
77+
__esModule: true,
78+
...jest.requireActual(`../dist/steps/source-nodes/fetch-nodes/fetch-referenced-media-items.js`),
79+
default: jest.fn(() => require(`./process-node.fixture`).referencedMediaItems)
80+
}
81+
})
82+
83+
84+
test(`Gatsby Image service works in html fields via replaceNodeHtmlImages`, async () => {
85+
const node = {
86+
content: `\n<p>Welcome to WordPress. This is your first post. Edit or deleteit, then start writing!</p>\n\n\n\n<p></p>\n\n\n\n<figureclass="wp-block-image size-large"><img loading="lazy" width="1024" height="768" src="http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-1024x768.jpg" alt=""class="wp-image-115" srcset="http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-1024x768.jpg 1024w,http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-300x225.jpg 300w, http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-768x576.jpg 768w,http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-1536x1152.jpg 1536w, http://wpgatsby.local/wp-content/uploads/2022/02/sasha-set-GURzQwO8Li0-unsplash-2048x1536.jpg 2048w"sizes="(max-width: 1024px) 100vw, 1024px" /></figure>\n`,
87+
id: `cG9zdDox`,
88+
modifiedGmt: `2022-02-18T23:18:00`,
89+
__typename: `Post`
90+
}
91+
92+
const gatsbyImageUrl = `/_gatsby/image`
93+
94+
const nodeString = JSON.stringify(node)
95+
96+
const updatedNodeString = await replaceNodeHtmlImages({
97+
nodeString,
98+
node,
99+
helpers: {
100+
reporter: console
101+
},
102+
wpUrl: `http://wpgatsby.local/`,
103+
pluginOptions: {
104+
html: {
105+
useGatsbyImage: true
106+
}
107+
}
108+
})
109+
110+
expect(updatedNodeString).toInclude(gatsbyImageUrl)
111+
expect(updatedNodeString).not.toEqual(nodeString)
112+
113+
const imageMatches = execall(/\/_gatsby\/image/gm, updatedNodeString)
114+
expect(imageMatches.length).toBe(39)
115+
116+
117+
const transformedNodeStringNoHtmlImages = await replaceNodeHtmlImages({
118+
nodeString,
119+
node,
120+
helpers: {
121+
reporter: console
122+
},
123+
wpUrl: `http://wpgatsby.local/`,
124+
pluginOptions: {
125+
html: {
126+
useGatsbyImage: false
127+
}
128+
}
129+
})
130+
131+
expect(transformedNodeStringNoHtmlImages).toEqual(nodeString)
132+
133+
const noImageMatches = execall(/\/_gatsby\/image/gm, transformedNodeStringNoHtmlImages)
134+
135+
expect(noImageMatches.length).toBe(0)
136+
137+
expect(transformedNodeStringNoHtmlImages).not.toInclude(gatsbyImageUrl)
138+
})

packages/gatsby-source-wordpress/docs/plugin-options.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
- [html.imageQuality](#htmlimagequality)
5151
- [html.createStaticFiles](#htmlcreatestaticfiles)
5252
- [html.generateWebpImages](#htmlgeneratewebpimages)
53+
- [html.placeholderType](#htmlplaceholdertype)
5354
- [type](#type)
5455
- [type.\_\_all](#type__all)
5556
- [type.\_\_all.where](#type__allwhere)
@@ -60,6 +61,7 @@
6061
- [type.\_\_all.beforeChangeNode](#type__allbeforechangenode)
6162
- [type.RootQuery](#typerootquery)
6263
- [type.MediaItem](#typemediaitem)
64+
- [type.MediaItem.placeholderSizeName](#typemediaitemplaceholdersizename)
6365
- [type.MediaItem.createFileNodes](#typemediaitemcreatefilenodes)
6466
- [type.MediaItem.lazyNodes](#typemediaitemlazynodes)
6567
- [type.MediaItem.localFile](#typemediaitemlocalfile)
@@ -951,7 +953,7 @@ If a max width can't be inferred from html this value will be passed to Sharp. I
951953

952954
**Field type**: `Number`
953955

954-
**Default value**: `100`
956+
**Default value**: `1024`
955957

956958
```js
957959
{
@@ -1025,6 +1027,14 @@ When this is true, .webp images will be generated for images in html fields in a
10251027

10261028
```
10271029

1030+
### html.placeholderType
1031+
1032+
This can be either "blurred" or "dominantColor". This is the type of placeholder image to be used in Gatsby Images in HTML fields.
1033+
1034+
**Field type**: `String`
1035+
1036+
**Default value**: `blurred`
1037+
10281038
## type
10291039

10301040
Options related to specific types in the remote schema.
@@ -1179,6 +1189,14 @@ A special type which is applied to any non-node root fields that are ingested an
11791189

11801190
**Field type**: `Object`
11811191

1192+
#### type.MediaItem.placeholderSizeName
1193+
1194+
This option allows you to choose the placeholder size used in the new Gatsby image service (currently in ALPHA/BETA) for the small placeholder image. Please make this image size very small for better performance. 20px or smaller width is recommended. To use, create a new image size in WP and name it "gatsby-image-placeholder" (or the name that you pass to this option) and that new size will be used automatically for placeholder images in the Gatsby build.
1195+
1196+
**Field type**: `String`
1197+
1198+
**Default value**: `gatsby-image-placeholder`
1199+
11821200
#### type.MediaItem.createFileNodes
11831201

11841202
This option controls whether or not a File node will be automatically created for each MediaItem node (available on MediaItem.localFile). Set this to false if you don't want Gatsby to download the corresponding file for each media item.

packages/gatsby-source-wordpress/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"gatsby-core-utils": "^3.10.0-next.0",
3232
"gatsby-plugin-catch-links": "^4.10.0-next.0",
3333
"gatsby-source-filesystem": "^4.10.0-next.0",
34+
"gatsby-plugin-utils": "^3.4.0-next.0",
3435
"glob": "^7.2.0",
3536
"got": "^11.8.3",
3637
"lodash": "^4.17.21",

packages/gatsby-source-wordpress/src/gatsby-node.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module.exports = runApisInSteps({
3737
],
3838

3939
onCreateDevServer: [
40+
steps.imageRoutes,
4041
steps.setImageNodeIdCache,
4142
steps.logPostBuildWarnings,
4243
steps.startPollingForContentUpdates,

packages/gatsby-source-wordpress/src/models/gatsby-api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ export interface IPluginOptions {
104104
fallbackImageMaxWidth?: number
105105
imageQuality?: number
106106
createStaticFiles?: boolean
107+
placeholderType?: `blurred` | `dominantColor`
107108
}
108109
presets?: Array<IPluginOptionsPreset>
109110
type?: {
@@ -123,6 +124,8 @@ export interface IPluginOptions {
123124
maxFileSizeBytes?: number
124125
requestConcurrency?: number
125126
}
127+
128+
placeholderSizeName?: string
126129
}
127130
}
128131
}
@@ -191,6 +194,8 @@ const defaultPluginOptions: IPluginOptions = {
191194
//
192195
// this adds image options to images in HTML fields when html.useGatsbyImage is also set
193196
gatsbyImageOptions: {},
197+
198+
placeholderType: `blurred`,
194199
},
195200
presets: [previewOptimizationPreset],
196201
type: {
@@ -226,6 +231,7 @@ const defaultPluginOptions: IPluginOptions = {
226231
exclude: true,
227232
},
228233
MediaItem: {
234+
placeholderSizeName: `gatsby-image-placeholder`,
229235
lazyNodes: false,
230236
createFileNodes: true,
231237
localFile: {

packages/gatsby-source-wordpress/src/steps/create-schema-customization/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getGatsbyNodeTypeNames } from "../source-nodes/fetch-nodes/fetch-nodes"
77
import { typeIsExcluded } from "~/steps/ingest-remote-schema/is-excluded"
88
import { formatLogMessage } from "../../utils/format-log-message"
99
import { CODES } from "../../utils/report"
10+
import { addRemoteFilePolyfillInterface } from "gatsby-plugin-utils/polyfill-remote-file"
1011

1112
/**
1213
* createSchemaCustomization
@@ -89,6 +90,20 @@ const customizeSchema = async ({ actions, schema }) => {
8990
isAGatsbyNode: true,
9091
})
9192

93+
typeDefs.push(
94+
addRemoteFilePolyfillInterface(
95+
schema.buildObjectType({
96+
name: pluginOptions.schema.typePrefix + `MediaItem`,
97+
fields: {},
98+
interfaces: [`Node`, `RemoteFile`],
99+
}),
100+
{
101+
schema,
102+
actions,
103+
}
104+
)
105+
)
106+
92107
typeDefs.push(wpType)
93108

94109
actions.createTypes(typeDefs)

0 commit comments

Comments
 (0)