121 lines
3 KiB
JavaScript
121 lines
3 KiB
JavaScript
/* eslint-env node */
|
|
const path = require('path');
|
|
|
|
/**
|
|
* Generates a set of pages that are blog-like, where there should be an
|
|
* "landing page" that needs to be paginated followed by individual items.
|
|
*
|
|
* This function does two essential features:
|
|
* 1. renders individual pages
|
|
* 2. renders index pages with context needed for pagination
|
|
*
|
|
* @param {function} createPage Gatsby createPage function
|
|
* @param {function} graphql Gatsby graphql function
|
|
* @param {object} reporter Gatbsy reporter object
|
|
* @param {string} queryAbsolutePathGlob The source code glob to find the pages
|
|
* for rendering
|
|
* @param {string} siteRootPath The public root path to generate the pages under
|
|
* @param {string} indexFilePath The source code path to the index template file
|
|
* @param {string} itemFilePath The source code path to the item template file
|
|
*/
|
|
async function generatePages(
|
|
createPage,
|
|
graphql,
|
|
reporter,
|
|
queryAbsolutePathGlob,
|
|
siteRootPath,
|
|
indexFilePath,
|
|
itemFilePath
|
|
) {
|
|
const result = await graphql(`
|
|
{
|
|
allMdx(
|
|
filter: { fileAbsolutePath: { glob: "${queryAbsolutePathGlob}" } }
|
|
) {
|
|
edges {
|
|
node {
|
|
frontmatter {
|
|
path
|
|
hidden
|
|
}
|
|
id
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`);
|
|
|
|
if (result.errors) {
|
|
reporter.panicOnBuild(`Error while running GraphQL query.`);
|
|
return;
|
|
}
|
|
|
|
const posts = result.data.allMdx.edges.filter(
|
|
({ node }) => !node.frontmatter.hidden
|
|
);
|
|
const postsPerPage = 10;
|
|
const numPages = Math.ceil(posts.length / postsPerPage);
|
|
|
|
Array.from({ length: numPages }).forEach((_, i) => {
|
|
createPage({
|
|
path: siteRootPath + (i === 0 ? '' : `/${i + 1}`),
|
|
component: path.resolve(indexFilePath),
|
|
context: {
|
|
limit: postsPerPage,
|
|
skip: i * postsPerPage,
|
|
numPages,
|
|
currentPage: i + 1,
|
|
rootPath: siteRootPath,
|
|
},
|
|
});
|
|
});
|
|
|
|
// Must decouple to ensure hidden pages are still rendered, just excluded from
|
|
// notes mapping
|
|
result.data.allMdx.edges.forEach(({ node }) => {
|
|
createPage({
|
|
path: `${siteRootPath}/${node.frontmatter.path}`,
|
|
component: path.resolve(itemFilePath),
|
|
context: {
|
|
id: node.id,
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
exports.createPages = async ({ actions, graphql, reporter }) => {
|
|
const { createPage } = actions;
|
|
await generatePages(
|
|
createPage,
|
|
graphql,
|
|
reporter,
|
|
'**/src/notes/*',
|
|
'/notes',
|
|
'./src/templates/notes.tsx',
|
|
'./src/templates/note.tsx',
|
|
);
|
|
await generatePages(
|
|
createPage,
|
|
graphql,
|
|
reporter,
|
|
'**/src/projects/*',
|
|
'/projects',
|
|
'./src/templates/projects.tsx',
|
|
'./src/templates/project.tsx',
|
|
);
|
|
};
|
|
|
|
exports.createSchemaCustomization = ({ actions: { createTypes } }) => {
|
|
createTypes(`
|
|
type Mdx implements Node {
|
|
frontmatter: CommonFrontmatter
|
|
}
|
|
|
|
type CommonFrontmatter {
|
|
hidden: Boolean,
|
|
lang: String,
|
|
tags: [String],
|
|
subtitle: String,
|
|
}
|
|
`);
|
|
};
|