-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgatsby-node.js
219 lines (195 loc) · 5.23 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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// keep at top of file
// require('dotenv').config({
// path: `.env.${process.env.NODE_ENV}`,
// });
const path = require('path');
const startCase = require('lodash.startcase');
const properUrlJoin = require('proper-url-join');
const ENABLE_DRAFTS = process.env.GATSBY_ENABLE_DRAFTS === 'true';
const urlJoin = (url = []) =>
properUrlJoin(...url, { leadingSlash: true, trailingSlash: true });
const onCreateNode = ({ actions, getNode, node }) => {
// nodes in gatsby are the main data interface. everything is a node.
// gatsby creates nodes (data) THEN creates pages.
if (node.internal.type === 'Mdx') {
// markdown nodes/pages
const mdxPage = getNode(node.parent);
const {
ext,
name: pageName,
relativeDirectory,
relativePath,
sourceInstanceName,
} = mdxPage;
// make index the root page of the folder
const isIndex = pageName === 'index';
const pageSlug = isIndex ? '' : pageName;
// documentation section
const isDocs = sourceInstanceName === 'docs';
const slug = isDocs
? urlJoin(['documentation', relativeDirectory, pageSlug])
: urlJoin([relativePath.replace(ext, '')]);
actions.createNodeField({
// relative URL of the page
name: `slug`,
node,
value: slug,
});
actions.createNodeField({
// need this to make per-page graphQL queries
name: 'id',
node,
value: node.id,
});
const title =
node.frontmatter.title ||
startCase(pageSlug) ||
(isDocs &&
isIndex &&
startCase(
relativeDirectory
.split('/')
.filter((x) => x)
.pop()
)) ||
'';
actions.createNodeField({
// frontmatter title field
name: 'title',
node,
value: title,
});
const sectionSlug = relativeDirectory
.split('/')
.filter((x) => x)
.shift();
actions.createNodeField({
name: 'sectionSlug',
node,
value: sectionSlug,
});
const isDraft = node.frontmatter.draft && node.frontmatter.draft === true;
actions.createNodeField({
name: 'draft',
node,
value: isDraft,
});
}
};
const createPages = async (params) => {
// use promise.all to build different page types concurrently.
// required when using external APIs for content.
await Promise.all([createMarkdownPages(params)]);
};
const createMarkdownPages = async ({ actions, graphql }) => {
const { data } = await graphql(`
{
allMdx {
nodes {
fields {
draft
id
sectionSlug
slug
}
}
}
allYaml {
nodes {
sectionSlug
pages {
isHeading
title
url
pages {
title
url
pages {
title
url
}
}
}
}
}
}
`);
data.allMdx.nodes
.filter((node) => ENABLE_DRAFTS || !node.fields.draft)
.forEach((node) => {
const { id, sectionSlug, slug } = node.fields;
// documentation section
actions.createPage({
path: slug,
component: path.resolve('src/templates/documentation/index.js'),
context: {
// use for graphQL query in template
id,
sectionSlug,
},
});
});
};
const onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({
resolve: {
alias: {
components: path.resolve(__dirname, 'src/components'),
constants: path.resolve(__dirname, 'constants'),
data: path.resolve(__dirname, 'src/data'),
hooks: path.resolve(__dirname, 'src/hooks'),
meta: path.resolve(__dirname, 'meta'),
pages: path.resolve(__dirname, 'src/pages'),
styles: path.resolve(__dirname, 'src/styles'),
templates: path.resolve(__dirname, 'src/templates'),
utils: path.resolve(__dirname, 'utils.js'),
},
},
});
};
const createSchemaCustomization = ({ actions }) => {
// DOCUMENTATION PAGE TYPES
// for YAML:
// - describe structure of _contents.yaml
// - throw descriptive errors if required fields are missing
// - prevent build failures if optional fields are missing,
// i.e. if none of the sections are nested 4 levels deep.
// for MDX: define optional fields (added in createNode) in MdxFields.
// otherwise, if none of the pages have that field,
// the build will fail.
const documentationTypeDefs = `
type Yaml implements Node {
sectionSlug: String!
pages: [YamlPages!]
}
type YamlPages implements Node {
isHeading: Boolean
title: String!
url: String!
pages: [YamlPagesPages!]
}
type YamlPagesPages implements Node {
skipPage: Boolean
title: String!
url: String!
pages: [YamlPagesPagesPages!]
}
type YamlPagesPagesPages implements Node {
title: String!
url: String!
}
type MdxFields implements Node {
draft: Boolean
}
type Mdx implements Node {
fields: MdxFields
}
`;
actions.createTypes(documentationTypeDefs);
};
module.exports = {
createPages,
createSchemaCustomization,
onCreateNode,
onCreateWebpackConfig,
};