Files
website/gatsby-node.js
T

215 lines
5.1 KiB
JavaScript

const { graphql } = require("gatsby")
const { createFilePath } = require("gatsby-source-filesystem")
const helper = require("./scripts/buildHelpers")
const path = require(`path`)
const fs = require("fs")
const requiredArticleFrontmatter = ["authors", "date"]
const LAYOUT_RESOURCES = "resources"
const LAYOUT_ARCHIVES = "archives"
const LAYOUT_REGULAR = "regular"
const LAYOUT_HOME = "home"
function resolveLayout(path) {
if (path === "/") {
return LAYOUT_HOME
}
if (path.match(/resources/)) {
return LAYOUT_RESOURCES
}
if (path.match(/archives/)) {
return LAYOUT_ARCHIVES
}
return LAYOUT_REGULAR
}
let users = []
try {
users = JSON.parse(fs.readFileSync("./users.json", "utf-8"))
console.log("(◕◡◕✿) Users list loaded!")
} catch (e) {
console.log("(◕‸ ◕✿) Users list not present, skipping user resolution...")
}
const validateResourceArticle = node => {
const missingField = requiredArticleFrontmatter.find(
required => node.frontmatter[required]
)
if (missingField) {
console.error(
`Article ${node.fileAbsolutePath} is missing field '${missingField}'`
)
process.exit(1)
}
}
const createResources = async ({ createPage, graphql }) => {
const resourcePage = path.resolve(`src/templates/resourcePage.tsx`)
const resourceHome = path.resolve(`src/templates/resourceHome.tsx`)
const languagesQuery = await graphql(
`
query FetchLanguages {
allFile(filter: { sourceInstanceName: { eq: "languages" } }) {
edges {
node {
relativePath
sourceInstanceName
}
}
}
}
`
)
const topicsQuery = await graphql(
`
query FetchTopics {
allFile(filter: { sourceInstanceName: { eq: "topics" } }) {
edges {
node {
relativePath
sourceInstanceName
}
}
}
}
`
)
const resources = [
{ key: "topics", query: topicsQuery },
{ key: "languages", query: languagesQuery },
]
for ({ key, query } of resources) {
if (query.errors) {
return Promise.reject(query.errors)
}
const resources = query.data.allFile.edges.reduce((acc, { node }) => {
const [resourceCategory] = node.relativePath.split("/")
if (!acc.includes(resourceCategory)) {
acc.push(resourceCategory)
}
return acc
}, [])
// create home page for each resources
resources.forEach((resource) => {
createPage({
path: path.posix.join("resources", resource),
component: resourceHome,
context: {
resourceType: key,
entry: resource,
layout: LAYOUT_RESOURCES,
},
})
})
query.data.allFile.edges.forEach(({ node }) => {
createPage({
path: path.posix.join("resources", node.relativePath),
component: resourcePage,
context: {
file: node.relativePath,
layout: LAYOUT_RESOURCES,
},
})
})
}
}
const createArchives = async ({ createPage, graphql }) => {
const archive = path.resolve(`src/templates/archive.tsx`)
const result = await graphql(`
query FetchArchives {
allFile(filter: { sourceInstanceName: { eq: "what-is-archive" } }) {
edges {
node {
relativePath
sourceInstanceName
}
}
}
}
`)
if (result.errors) {
return Promise.reject(result.errors)
}
return result.data.allFile.edges.forEach(({ node }) => {
createPage({
path: path.posix.join("archives", node.relativePath),
component: archive,
context: {
file: node.relativePath,
layout: LAYOUT_ARCHIVES,
},
})
})
}
exports.onCreateNode = async ({ node, getNode, actions }) => {
const { createPage, createNodeField } = actions
// TODO: find a better way to avoid handling non-resources
// or better, attach authors to what-is archives
if (node.internal.type === "Mdx" && node.frontmatter.authors) {
const { frontmatter } = node
const isDoc = Boolean(!frontmatter.path)
const githubLink = helper.findMarkdownLink(node.fileAbsolutePath)
createNodeField({
node,
name: "githubLink",
value: githubLink,
})
if (!isDoc) {
return
}
const authors = helper.resolveAuthors(users, frontmatter.authors)
createNodeField({
node,
name: "authors",
value: authors,
})
}
}
exports.onCreatePage = async ({ page, actions }) => {
const { createPage, deletePage } = actions
if (page.path.match(/^\/resources\/404/)) {
const oldPage = { ...page }
page.matchPath = `/resources/*`
deletePage(oldPage)
} else if (page.path.match(/^\/archives\/404/)) {
const oldPage = { ...page }
page.matchPath = `/archives/*`
deletePage(oldPage)
}
page.context.layout = resolveLayout(page.path)
createPage(page)
}
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions
return Promise.all([
createArchives({ createPage, graphql }),
createResources({ createPage, graphql }),
])
}