Skip to content

Commit 496cb5d

Browse files
fix(gatsby-remark-images): support resolving markdown images from child nodes (#28093)
* fix(gatsby-remark-images): support resolving markdown images from child nodes - in case where remark nodes are created from other nodes (e.g. gatsby-plugin-json-remark) the parent node of a remark document is not a file. - in order to resolve the images still, it is necessary to go up the parent chain until the closest File node * fix snapshots * Revert unrelated snapshot change * Set windows timeout to 15m * Fix Co-authored-by: Kyle Mathews <[email protected]>
1 parent 9f450e1 commit 496cb5d

File tree

4 files changed

+105
-1
lines changed

4 files changed

+105
-1
lines changed

.circleci/config.yml

+1
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ jobs:
540540
- run:
541541
name: Run tests
542542
command: yarn jest --ci --runInBand ((yarn jest --listTests) | Foreach-Object {$_ -replace '.*\\packages', 'packages'} | Foreach-Object {$_ -replace '\\', '/'} | circleci tests split --split-by=timings)
543+
no_output_timeout: 15m
543544
environment:
544545
NODE_OPTIONS: --max-old-space-size=2048
545546
GENERATE_JEST_REPORT: "true"

packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap

+31
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,37 @@ exports[`it transforms images in markdown and uses getRemarkFileDependency when
297297
</span>"
298298
`;
299299

300+
exports[`it transforms images in markdown in nested markdown node 1`] = `
301+
"<span
302+
class=\\"gatsby-resp-image-wrapper\\"
303+
style=\\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px; \\"
304+
>
305+
<a
306+
class=\\"gatsby-resp-image-link\\"
307+
href=\\"not-a-real-dir/images/my-image.jpeg\\"
308+
style=\\"display: block\\"
309+
target=\\"_blank\\"
310+
rel=\\"noopener\\"
311+
>
312+
<span
313+
class=\\"gatsby-resp-image-background-image\\"
314+
style=\\"padding-bottom: 133.33333333333331%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw'); background-size: cover; display: block;\\"
315+
></span>
316+
<img
317+
class=\\"gatsby-resp-image-image\\"
318+
alt=\\"image\\"
319+
title=\\"image\\"
320+
src=\\"not-a-real-dir/images/my-image.jpeg\\"
321+
srcset=\\"not-a-real-dir/images/my-image.jpeg, not-a-real-dir/images/my-image.jpeg\\"
322+
sizes=\\"(max-width: 650px) 100vw, 650px\\"
323+
style=\\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\\"
324+
loading=\\"lazy\\"
325+
decoding=\\"async\\"
326+
/>
327+
</a>
328+
</span>"
329+
`;
330+
300331
exports[`it transforms images in markdown with query strings 1`] = `
301332
"<span
302333
class=\\"gatsby-resp-image-wrapper\\"

packages/gatsby-remark-images/src/__tests__/index.js

+48
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,37 @@ const createPluginOptions = (
9898
getRemarkFileDependency,
9999
}
100100
}
101+
const createRecursivePluginOptions = (content, imagePaths = `/`) => {
102+
const dirName = `not-a-real-dir`
103+
return {
104+
files: [].concat(imagePaths).map(imagePath => {
105+
return {
106+
absolutePath: queryString.parseUrl(`${dirName}/${imagePath}`).url,
107+
}
108+
}),
109+
markdownNode: createNode(content),
110+
markdownAST: remark.parse(content),
111+
getNode: id => {
112+
if (id === 1234) {
113+
return {
114+
id: 1234,
115+
internal: { type: `JsonRemarkProperty` },
116+
parent: 2345,
117+
}
118+
}
119+
return {
120+
dir: dirName,
121+
internal: {
122+
type: `File`,
123+
},
124+
}
125+
},
126+
compiler: {
127+
parseString: remark.parse.bind(remark),
128+
generateHTML: node => hastToHTML(toHAST(node)),
129+
},
130+
}
131+
}
101132

102133
test(`it returns empty array when 0 images`, async () => {
103134
const content = `
@@ -170,6 +201,23 @@ test(`it transforms images in markdown`, async () => {
170201
expect(node.value).not.toMatch(`<html>`)
171202
})
172203

204+
test(`it transforms images in markdown in nested markdown node`, async () => {
205+
const imagePath = `images/my-image.jpeg`
206+
const content = `
207+
208+
![image](./${imagePath})
209+
`.trim()
210+
211+
const nodes = await plugin(createRecursivePluginOptions(content, imagePath))
212+
213+
expect(nodes.length).toBe(1)
214+
215+
const node = nodes.pop()
216+
expect(node.type).toBe(`html`)
217+
expect(node.value).toMatchSnapshot()
218+
expect(node.value).not.toMatch(`<html>`)
219+
})
220+
173221
test(`it transforms images in markdown with the "withWebp" option`, async () => {
174222
const imagePath = `images/my-image.jpeg`
175223
const content = `

packages/gatsby-remark-images/src/index.js

+25-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,31 @@ module.exports = (
143143
) {
144144
// Check if this markdownNode has a File parent. This plugin
145145
// won't work if the image isn't hosted locally.
146-
const parentNode = getNode(markdownNode.parent)
146+
let parentNode = getNode(markdownNode.parent)
147+
// check if the parent node is a File node, otherwise go up the chain and
148+
// search for the closest parent File node. This is necessary in case
149+
// you have markdown in child nodes (e.g. gatsby-plugin-json-remark).
150+
if (
151+
parentNode &&
152+
parentNode.internal &&
153+
parentNode.internal.type !== `File`
154+
) {
155+
let tempParentNode = parentNode
156+
while (
157+
tempParentNode &&
158+
tempParentNode.internal &&
159+
tempParentNode.internal.type !== `File`
160+
) {
161+
tempParentNode = getNode(tempParentNode.parent)
162+
}
163+
if (
164+
tempParentNode &&
165+
tempParentNode.internal &&
166+
tempParentNode.internal.type === `File`
167+
) {
168+
parentNode = tempParentNode
169+
}
170+
}
147171
let imagePath
148172
if (parentNode && parentNode.dir) {
149173
imagePath = slash(path.join(parentNode.dir, getImageInfo(node.url).url))

0 commit comments

Comments
 (0)