rickvanlieshout.com/internal/gatsby/create-pages.ts

154 lines
3.8 KiB
TypeScript

import { GatsbyNode } from "gatsby";
import * as constants from "./constants";
import * as queries from "./queries";
import * as utils from "./utils";
type CreateWithPagination = (parameters: {
limit: number;
group?: string;
template: string;
total: number;
page: number;
path: string;
}) => void;
const getPaginationPath = (basePath: string, page: number): string =>
[basePath === "/" ? "" : basePath, "page", page].join("/");
const createPages: GatsbyNode["createPages"] = async ({ graphql, actions }) => {
const { createPage } = actions;
createPage({
path: constants.routes.notFoundRoute,
component: constants.templates.notFoundTemplate,
context: {},
});
createPage({
path: constants.routes.tagsListRoute,
component: constants.templates.tagsTemplate,
context: {},
});
createPage({
path: constants.routes.categoriesListRoute,
component: constants.templates.categoriesTemplate,
context: {},
});
const pages = await queries.pagesQuery(graphql);
const { pageTemplate, postTemplate } = constants.templates;
pages.forEach((edge) => {
const { node } = edge;
if (node?.fields?.slug) {
switch (node?.frontmatter?.template) {
case "page":
case "portfolioItem":
createPage({
path: node.fields.slug,
component: pageTemplate,
context: { slug: node.fields.slug },
});
break;
case "post":
createPage({
path: node.fields.slug,
component: postTemplate,
context: { slug: node.fields.slug, readingTime: node?.fields?.readingTime },
});
break;
}
}
});
const createWithPagination: CreateWithPagination = ({
group,
template,
page,
path,
total,
limit,
}) => {
createPage({
component: template,
path: page === 0 ? path : getPaginationPath(path, page),
context: {
group,
limit,
offset: page * limit,
pagination: {
currentPage: page,
prevPagePath: page <= 1 ? path : getPaginationPath(path, utils.decrement(page)),
nextPagePath: getPaginationPath(path, utils.increment(page)),
hasNextPage: page !== utils.decrement(total),
hasPrevPage: page !== 0,
},
},
});
};
const categories = await queries.categoriesQuery(graphql);
const metadata = await queries.metadataQuery(graphql);
const postsLimit = metadata?.postsLimit ?? 1;
categories.forEach((category) => {
const total = Math.ceil(category.totalCount / postsLimit);
const path = utils.concat(
constants.routes.categoryRoute,
"/",
utils.toKebabCase(category.fieldValue)
);
for (let page = 0; page < total; page += 1) {
createWithPagination({
limit: postsLimit,
group: category.fieldValue,
template: constants.templates.categoryTemplate,
total,
page,
path,
});
}
});
const tags = await queries.tagsQuery(graphql);
tags.forEach((tag) => {
const path = utils.concat(constants.routes.tagRoute, "/", utils.toKebabCase(tag.fieldValue));
const total = Math.ceil(tag.totalCount / postsLimit);
for (let page = 0; page < total; page += 1) {
createWithPagination({
limit: postsLimit,
group: tag.fieldValue,
template: constants.templates.tagTemplate,
total,
page,
path,
});
}
});
const path = constants.routes.indexRoute;
const template = constants.templates.indexTemplate;
const posts = await queries.postsQuery(graphql);
const total = Math.ceil((posts?.edges?.length ?? 0) / postsLimit);
for (let page = 0; page < total; page += 1) {
createWithPagination({
limit: postsLimit,
template,
total,
page,
path,
});
}
};
export { createPages };