-
Notifications
You must be signed in to change notification settings - Fork 39
/
gatsby-node.js
107 lines (96 loc) · 3.01 KB
/
gatsby-node.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
const { createRemoteFileNode } = require(`gatsby-source-filesystem`)
const get = require('lodash/get')
exports.onCreateNode = async (
{ node, actions, store, cache, createNodeId },
options
) => {
const { createNode } = actions
const {
nodeType,
imagePath,
name = 'localImage',
auth = {},
ext = null,
prepareUrl = null,
} = options
const createImageNodeOptions = {
store,
cache,
createNode,
createNodeId,
auth,
ext,
name,
prepareUrl,
}
if (node.internal.type === nodeType) {
// Check if any part of the path indicates the node is an array and splits at those indicators
let imagePathSegments = []
if (imagePath.includes("[].")) {
imagePathSegments = imagePath.split("[].")
}
if (imagePathSegments.length) {
await createImageNodesInArrays(imagePathSegments[0], node, { imagePathSegments, ...createImageNodeOptions })
} else {
const url = getPath(node, imagePath, ext)
await createImageNode(url, node, createImageNodeOptions)
}
}
}
// Returns value from path, adding extension when supplied
function getPath(node, path, ext = null) {
const value = get(node, path)
return ext ? value + ext : value
}
// Creates a file node and associates the parent node to its new child
async function createImageNode(url, node, options) {
const { name, imagePathSegments, prepareUrl, ...restOfOptions } = options
let fileNode
if (!url) {
return
}
if (typeof prepareUrl === 'function') {
url = prepareUrl(url);
}
try {
fileNode = await createRemoteFileNode({
...restOfOptions,
url,
parentNodeId: node.id,
})
} catch (e) {
console.error('gatsby-plugin-remote-images ERROR:', e)
}
// Adds a field `localImage` or custom name to the node
// ___NODE appendix tells Gatsby that this field will link to another node
if (fileNode) {
node[`${name}___NODE`] = fileNode.id
}
}
// Recursively traverses objects/arrays at each path part, then operates on targeted leaf node
async function createImageNodesInArrays(path, node, options) {
if (!path || !node) {
return
}
const { imagePathSegments, ext } = options
const pathIndex = imagePathSegments.indexOf(path),
isPathToLeafProperty = pathIndex === imagePathSegments.length - 1,
nextValue = getPath(node, path, isPathToLeafProperty ? ext : null)
// grab the parent of the leaf property, if it's not the current value of `node` already
// ex: `parentNode` in `myNodes[].parentNode.leafProperty`
let nextNode = node
if (isPathToLeafProperty && path.includes('.')) {
const pathToLastParent = path
.split('.')
.slice(0, -1)
.join('.')
nextNode = get(node, pathToLastParent)
}
return Array.isArray(nextValue)
// Recursively call function with next path segment for each array element
? Promise.all(
nextValue.map(item => createImageNodesInArrays(imagePathSegments[pathIndex + 1], item, options))
)
// otherwise, handle leaf node
: createImageNode(nextValue, nextNode, options)
}