-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgatsby-node.js
204 lines (197 loc) · 6.31 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
const path = require("path")
const moment = require("moment")
const { createFilePath } = require(`gatsby-source-filesystem`)
const blogPost = path.resolve(`./src/templates/blogPost.js`)
const page = path.resolve(`./src/templates/page.js`)
const project = path.resolve(`./src/templates/project.js`)
const smallProject = path.resolve(`./src/templates/smallProject.js`)
const blogYear = path.resolve(`./src/templates/blogYear.js`)
/**
* Create page slugs (each page's URL minus the base domain mame)
* - In general, the slug name is the project name, page name, or blog post title.
* - Blog posts should have /blog appended to the slug.
* - /mainData/ contains info for the homepage. For /mainData/, we're not actually making a slug,
* but rather a way to query to index page data by calling a markdown file with the name 'index'.
* (I should probably reimplement /mainData/ in the future since this could be confusing.)
*/
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
if (node.fileAbsolutePath.includes("/blogPosts/")) {
const slug = "/blog" + createFilePath({ node, getNode, basePath: `blog` })
createNodeField({
node,
name: `slug`,
value: slug,
})
} else if (node.fileAbsolutePath.includes("/mainData/")) {
const slug = path.basename(node.fileAbsolutePath, ".md")
createNodeField({
node,
name: `slug`,
value: slug,
})
} else {
const slug = createFilePath({ node, getNode })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
}
/**
* The above function just created the URL names of the pages.
* Now we'll actually form the pages.
* We create pages differently based on the type of page (project, blog post, etc.)
*/
module.exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const pageResponse = await graphql(`
query {
allMarkdownRemark(filter: { fileAbsolutePath: { regex: "/(pages)/" } }) {
edges {
node {
fields {
slug
}
}
}
}
}
`)
const projectResponse = await graphql(`
query {
allMarkdownRemark(filter: { fileAbsolutePath: { regex: "/(projects)/" } }) {
edges {
node {
fields {
slug
}
}
}
}
}
`)
const smallProjectResponse = await graphql(`
query {
allMarkdownRemark(filter: { fileAbsolutePath: { regex: "/(smallProjects)/" } }) {
edges {
node {
fields {
slug
}
}
}
}
}
`)
const blogPostResponse = await graphql(`
query {
allMarkdownRemark(
filter: { fileAbsolutePath: { regex: "/(blogPosts)/" } }
sort: { frontmatter: { date: DESC } }
) {
edges {
node {
fields {
slug
}
frontmatter {
date
}
}
}
}
}
`)
// For normal pages and projects, simply create a page using their respective component and slug
pageResponse.data.allMarkdownRemark.edges.forEach(edge => {
createPage({
component: page,
path: edge.node.fields.slug,
context: {
slug: edge.node.fields.slug,
},
})
})
projectResponse.data.allMarkdownRemark.edges.forEach(edge => {
createPage({
component: project,
path: edge.node.fields.slug,
context: {
slug: edge.node.fields.slug,
},
})
})
smallProjectResponse.data.allMarkdownRemark.edges.forEach(edge => {
createPage({
component: smallProject,
path: edge.node.fields.slug,
context: {
slug: edge.node.fields.slug,
},
})
})
// Blog posts are more tricky, so let's break this down.
// all_years is an object that will contain a year as a key and the total number of blog posts for
// that year as a value.
// Ex: {2020: 3, 2019: 4, 2018: 5} means 3 2020 posts, 4 2019 posts, and 5 2018 posts.
const all_years = {}
blogPostResponse.data.allMarkdownRemark.edges.forEach((edge, index) => {
// For every blog post, create the blog post page, adding info about the previous and next
// blog post by date for those links to work on each page.
createPage({
component: blogPost,
path: edge.node.fields.slug,
context: {
slug: edge.node.fields.slug,
prev:
index === 0
? null
: blogPostResponse.data.allMarkdownRemark.edges[index - 1].node.fields.slug,
next:
index === blogPostResponse.data.allMarkdownRemark.edges.length - 1
? null
: blogPostResponse.data.allMarkdownRemark.edges[index + 1].node.fields.slug,
},
})
// Fill in the all_years object.
// All queried dates are in UTC, so adjust the year to your local timezone.
const the_year = moment(edge.node.frontmatter.date).local().format(`YYYY`)
all_years[the_year] = all_years[the_year] === undefined ? 1 : (all_years[the_year] += 1)
})
// With the all_years object, create the pages for the blog archive by year.
// endRange marks the final second of the year in question, adjusted to your timezone.
// Add the limit to ensure each page only gets that year's posts, and not anything older.
Object.keys(all_years).forEach(year => {
createPage({
component: blogYear,
path: `/blog/year/${year}/`,
context: {
slug: `/blog/year/${year}/`,
year: year,
endRange: `${(parseInt(year) + 1).toString()}-01-01T08:00:00.000Z`, // Change for timezone
limit: all_years[year],
},
})
})
// Create the pages for the general blog index.
// There should be 8 posts per page. Use a for loop to generate all the pages needed.
const posts = blogPostResponse.data.allMarkdownRemark.edges
const postsPerPage = 8
const numPages = Math.ceil(posts.length / postsPerPage)
Array.from({ length: numPages }).forEach((_, i) => {
createPage({
path: i === 0 ? `/blog/` : `/blog/${i + 1}/`,
component: path.resolve("./src/templates/blog.js"),
context: {
limit: postsPerPage,
skip: i * postsPerPage,
numPages,
currentPage: i + 1,
},
})
})
}