document #4507
This commit is contained in:
parent
a88ae25e57
commit
b7fcd80cae
10 changed files with 175 additions and 34 deletions
|
@ -19,8 +19,10 @@ import { PrevNext } from 'shared/components/prev-next.mjs'
|
|||
|
||||
export const ns = [navNs, 'docs'] //navNs
|
||||
|
||||
/** checks for a slug that isn't a post, to prevent a prev or next button to it */
|
||||
const isEndSlug = (slug) => slug.split('/').length === 1
|
||||
|
||||
/** layout for a page that displays a blog, showcase or newsletter */
|
||||
export const PostLayout = ({ children = [], slug, frontmatter, locale }) => {
|
||||
const { siteNav } = useNavigation({ ignoreControl: true })
|
||||
|
||||
|
|
|
@ -2,21 +2,32 @@ import { localePath } from 'shared/utils.mjs'
|
|||
const preGenerate = 6
|
||||
export const numPerPage = 12
|
||||
|
||||
export const getPostSlugPaths = (order) => {
|
||||
/**
|
||||
* get pre-generated paths for each language for post slug pages
|
||||
* @param {Object} sortedPaths a dictionary keyed by locale of post paths sorted by date published
|
||||
* @return {Sting[]} paths for the latest 6 posts in all locales
|
||||
*/
|
||||
export const getPostSlugPaths = (sortedPaths) => {
|
||||
const paths = []
|
||||
|
||||
for (const lang in order) {
|
||||
for (const lang in sortedPaths) {
|
||||
for (let i = 0; i < preGenerate; i++) {
|
||||
paths.push(localePath(lang, `${order[lang][i]}`))
|
||||
paths.push(localePath(lang, `${sortedPaths[lang][i]}`))
|
||||
}
|
||||
}
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
export const getPostIndexPaths = (order, type) => {
|
||||
/**
|
||||
* get pre-generated paths for each language for post index pages
|
||||
* @param {Object} sortedPaths a dictionary keyed by locale of post paths sorted by date published
|
||||
* @param {String} type post type: blog, showcase, or newsletter
|
||||
* @return {String[]} paths for the first two pages of posts in all locales
|
||||
*/
|
||||
export const getPostIndexPaths = (sortedPaths, type) => {
|
||||
const paths = []
|
||||
for (const language in order) {
|
||||
for (const language in sortedPaths) {
|
||||
paths.push(localePath(language, `${type}/page/1`))
|
||||
paths.push(localePath(language, `${type}/page/2`))
|
||||
}
|
||||
|
@ -24,12 +35,23 @@ export const getPostIndexPaths = (order, type) => {
|
|||
return paths
|
||||
}
|
||||
|
||||
export const getPostIndexProps = (locale, params, order, postInfo) => {
|
||||
/**
|
||||
* get static props for a post index page
|
||||
* @param {String} locale the locale
|
||||
* @param {Object} params path params
|
||||
* @param {Object} sortedPaths [description]
|
||||
* @param {Object} postInfo data on all posts, loaded from prebuild
|
||||
* @return {Object} props page props
|
||||
* @return {Object[]} props.posts the posts to link to on the page
|
||||
* @return {Number} props.current the current page number
|
||||
* @return {Number} props.total the total number of pages
|
||||
*/
|
||||
export const getPostIndexProps = (locale, params, sortedPaths, postInfo) => {
|
||||
const pageNum = parseInt(params.page)
|
||||
const numLocPages = Math.ceil(order[locale].length / numPerPage)
|
||||
const numLocPages = Math.ceil(sortedPaths[locale].length / numPerPage)
|
||||
if (pageNum > numLocPages) return false
|
||||
|
||||
const postSlugs = order[locale].slice(numPerPage * (pageNum - 1), numPerPage * pageNum)
|
||||
const postSlugs = sortedPaths[locale].slice(numPerPage * (pageNum - 1), numPerPage * pageNum)
|
||||
const posts = postSlugs.map((s) => ({ ...postInfo[locale][s], s }))
|
||||
|
||||
return { posts, current: pageNum, total: numLocPages }
|
||||
|
|
|
@ -53,6 +53,11 @@ const BlogPage = ({ locale, slug, page }) => {
|
|||
export async function getStaticProps({ params, locale }) {
|
||||
const { slug } = params
|
||||
|
||||
// if the slug isn't present in the prebuilt order, return 404
|
||||
if (order[locale].indexOf(`blog/${slug}`) === -1) {
|
||||
return { notFound: true }
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
slug,
|
||||
|
@ -66,6 +71,21 @@ export async function getStaticProps({ params, locale }) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getStaticPaths() is used to specify for which routes (think URLs)
|
||||
* this page should be used to generate the result.
|
||||
*
|
||||
* On this page, it is returning a truncated list of routes (think URLs) for all
|
||||
* the mdx blog (markdown) content.
|
||||
* That list comes from prebuild/blog-paths.mjs, which is built in the prebuild step
|
||||
* and contains paths, titles, imageUrls, and intro for all blog posts.
|
||||
*
|
||||
* the fallback: 'blocking' property means that
|
||||
* any pages that haven't been pre-generated
|
||||
* will generate and cache the first time someone visits them
|
||||
*
|
||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||
*/
|
||||
export const getStaticPaths = async () => {
|
||||
return {
|
||||
paths: getPostSlugPaths(order),
|
||||
|
|
|
@ -68,6 +68,7 @@ const Preview = ({ post, t }) => (
|
|||
</Link>
|
||||
</div>
|
||||
)
|
||||
|
||||
/*
|
||||
* Each page MUST be wrapped in the PageWrapper component.
|
||||
* You also MUST spread props.page into this wrapper component
|
||||
|
@ -90,9 +91,20 @@ const BlogIndexPage = ({ posts, page, current, total }) => {
|
|||
|
||||
export default BlogIndexPage
|
||||
|
||||
/*
|
||||
* getStaticProps() is used to fetch data at build-time.
|
||||
*
|
||||
* On this page, it fetches data for the blogs to be linked to on this page
|
||||
*
|
||||
* This, in combination with getStaticPaths() below means this
|
||||
* page will be used to link to all blogs.
|
||||
*
|
||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||
*/
|
||||
export async function getStaticProps({ locale, params }) {
|
||||
const props = getPostIndexProps(locale, params, order, postInfo)
|
||||
|
||||
// if there shouldn't be a page with these params, return 404
|
||||
if (props === false) return { notFound: true }
|
||||
|
||||
return {
|
||||
|
@ -108,6 +120,21 @@ export async function getStaticProps({ locale, params }) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getStaticPaths() is used to specify for which routes (think URLs)
|
||||
* this page should be used to generate the result.
|
||||
*
|
||||
* On this page, it is returning a truncated list of routes (think URLs) for pages that list and link to
|
||||
* the mdx blog (markdown) content.
|
||||
* That list comes from prebuild/blog-paths.mjs, which is built in the prebuild step
|
||||
* and contains paths, titles, imageUrls, and intro for all blog posts.
|
||||
*
|
||||
* the fallback: 'blocking' property means that
|
||||
* any pages that haven't been pre-generated
|
||||
* will generate and cache the first time someone visits them
|
||||
*
|
||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||
*/
|
||||
export const getStaticPaths = async () => {
|
||||
return {
|
||||
paths: getPostIndexPaths(order, 'blog'),
|
||||
|
|
|
@ -12,27 +12,13 @@ import { DocsLayout, ns as layoutNs } from 'site/components/layouts/docs.mjs'
|
|||
import { loaders } from 'shared/components/dynamic-docs/org.mjs'
|
||||
|
||||
export const ns = [...pageNs, layoutNs]
|
||||
/*
|
||||
* PLEASE READ THIS BEFORE YOU TRY TO REFACTOR THIS PAGE
|
||||
*
|
||||
* You will notice that this page has a page component for each language
|
||||
* and that those components are 95% identical. So you may be thinking:
|
||||
*
|
||||
* This is not DRY, let me refactor this real quick
|
||||
*
|
||||
* Before you do so, please reflect on these topics:
|
||||
*
|
||||
* - Do you know the pitfalls of dynamic imports in Webpack?
|
||||
* - Do you know how much documentation we have?
|
||||
* - Do you know we support 5 languages?
|
||||
*
|
||||
* If you do know all of these thigns, and you think you can improve this page. Go ahead.
|
||||
*
|
||||
* If you are not sure, then I would recommend you find something else to work on, unless
|
||||
* you consider this a learning opportunity.
|
||||
*
|
||||
* joost
|
||||
*
|
||||
|
||||
/**
|
||||
* a page to display documentation markdown
|
||||
* Each page MUST be wrapped in the PageWrapper component.
|
||||
* You also MUST spread props.page into this wrapper component
|
||||
* when path and locale come from static props (as here)
|
||||
* or set them manually.
|
||||
*/
|
||||
export const Page = ({ page, locale, frontmatter, MDX }) => (
|
||||
<PageWrapper
|
||||
|
@ -46,6 +32,7 @@ export const Page = ({ page, locale, frontmatter, MDX }) => (
|
|||
)
|
||||
|
||||
const DocsPage = ({ page, locale, slug }) => {
|
||||
// get the appropriate loader for the locale, and load the mdx for this page
|
||||
const loader = useCallback(() => loaders[locale](slug), [locale, slug])
|
||||
// State
|
||||
const { frontmatter, MDX } = useDynamicMdx(loader)
|
||||
|
@ -97,6 +84,6 @@ export async function getStaticPaths() {
|
|||
...somePaths.map((key) => `/fr/${key}`),
|
||||
...somePaths.map((key) => `/nl/${key}`),
|
||||
],
|
||||
fallback: 'blocking',
|
||||
fallback: false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,14 +9,21 @@ import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
|||
|
||||
const namespaces = [...layoutNs, ...postNs, ...pageNs]
|
||||
|
||||
/*
|
||||
* Each page MUST be wrapped in the PageWrapper component.
|
||||
* You also MUST spread props.page into this wrapper component
|
||||
* when path and locale come from static props (as here)
|
||||
* or set them manually.
|
||||
*/
|
||||
const ShowcasePage = ({ locale, slug, page }) => {
|
||||
// function to load the correct markdown
|
||||
const loader = useCallback(
|
||||
() => import(`orgmarkdown/showcase/${slug}/${locale}.md`),
|
||||
[slug, locale]
|
||||
)
|
||||
|
||||
const { frontmatter, MDX } = useDynamicMdx(loader)
|
||||
if (!MDX) return null
|
||||
|
||||
return (
|
||||
<PageWrapper
|
||||
{...page}
|
||||
|
@ -39,7 +46,7 @@ const ShowcasePage = ({ locale, slug, page }) => {
|
|||
/*
|
||||
* getStaticProps() is used to fetch data at build-time.
|
||||
*
|
||||
* On this page, it is loading the showcase content from strapi.
|
||||
* On this page, it it passes the name of the bundle to be loaded on the client.
|
||||
*
|
||||
* This, in combination with getStaticPaths() below means this
|
||||
* page will be used to render/generate all showcase content.
|
||||
|
@ -49,6 +56,11 @@ const ShowcasePage = ({ locale, slug, page }) => {
|
|||
export async function getStaticProps({ params, locale }) {
|
||||
const { slug } = params
|
||||
|
||||
// if the slug isn't present in the prebuilt order, return 404
|
||||
if (order[locale].indexOf(`showcase/${slug}`) === -1) {
|
||||
return { notFound: true }
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
slug,
|
||||
|
@ -62,6 +74,21 @@ export async function getStaticProps({ params, locale }) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getStaticPaths() is used to specify for which routes (think URLs)
|
||||
* this page should be used to generate the result.
|
||||
*
|
||||
* On this page, it is returning a truncated list of routes (think URLs) for all
|
||||
* the mdx showcase (markdown) content.
|
||||
* That list comes from prebuild/showcase-paths.mjs, which is built in the prebuild step
|
||||
* and contains paths, titles, imageUrls, and intro for all showcase posts.
|
||||
*
|
||||
* the fallback: 'blocking' property means that
|
||||
* any pages that haven't been pre-generated
|
||||
* will generate and cache the first time someone visits them
|
||||
*
|
||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||
*/
|
||||
export const getStaticPaths = async () => {
|
||||
return {
|
||||
paths: getPostSlugPaths(order),
|
||||
|
|
|
@ -58,6 +58,12 @@ const Posts = ({ posts }) => {
|
|||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* Each page MUST be wrapped in the PageWrapper component.
|
||||
* You also MUST spread props.page into this wrapper component
|
||||
* when path and locale come from static props (as here)
|
||||
* or set them manually.
|
||||
*/
|
||||
const ShowcaseIndexPage = ({ posts, page, current, total }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
|
@ -74,9 +80,20 @@ const ShowcaseIndexPage = ({ posts, page, current, total }) => {
|
|||
|
||||
export default ShowcaseIndexPage
|
||||
|
||||
/*
|
||||
* getStaticProps() is used to fetch data at build-time.
|
||||
*
|
||||
* On this page, it fetches data for the showcases to be linked to on this page
|
||||
*
|
||||
* This, in combination with getStaticPaths() below means this
|
||||
* page will be used to link to all showcases.
|
||||
*
|
||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||
*/
|
||||
export async function getStaticProps({ locale, params }) {
|
||||
const props = getPostIndexProps(locale, params, order, postInfo)
|
||||
|
||||
// if there shouldn't be a page with these params, return 404
|
||||
if (props === false) return { notFound: true }
|
||||
|
||||
return {
|
||||
|
@ -92,6 +109,21 @@ export async function getStaticProps({ locale, params }) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getStaticPaths() is used to specify for which routes (think URLs)
|
||||
* this page should be used to generate the result.
|
||||
*
|
||||
* On this page, it is returning a truncated list of routes (think URLs) for pages that list and link to
|
||||
* the mdx showcase (markdown) content.
|
||||
* That list comes from prebuild/showcase-paths.mjs, which is built in the prebuild step
|
||||
* and contains paths, titles, imageUrls, and intro for all showcase posts.
|
||||
*
|
||||
* the fallback: 'blocking' property means that
|
||||
* any pages that haven't been pre-generated
|
||||
* will generate and cache the first time someone visits them
|
||||
*
|
||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||
*/
|
||||
export const getStaticPaths = async () => {
|
||||
return {
|
||||
paths: getPostIndexPaths(order, 'showcase'),
|
||||
|
|
|
@ -31,14 +31,32 @@ const NextPage = ({ t, s }) =>
|
|||
<span></span>
|
||||
)
|
||||
|
||||
/**
|
||||
* get slug at the given index, or null if it should not be displayed
|
||||
* @param {Number} index the index of the page to get
|
||||
* @param {String[]} slugLut the lut for navigation slugs
|
||||
* @param {Object} siteNav nav data
|
||||
* @param {Boolen | Function} shouldHide should this element be hidden?
|
||||
* Function arguments should accept the slug that this element would display and return a boolean
|
||||
* @return {String | null} the slug for the page, or null if it shouldn't display
|
||||
*/
|
||||
const getItemWithCaveat = (index, slugLut, siteNav, shouldHide) => {
|
||||
// boolean shouldHide, return null
|
||||
if (shouldHide === true) return null
|
||||
|
||||
// function shouldHide, return null if it returns true
|
||||
if (typeof shouldHide === 'function' && shouldHide(slugLut[index])) return null
|
||||
|
||||
// get the slug at the index
|
||||
return get(siteNav, slugLut[index].split('/'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Previous and Next buttons
|
||||
* @param {String} options.slug the current slug
|
||||
* @param {Boolean | Function} options.noPrev should the previous button be hidden? You can pass a function that accepts the slug for the previous button and returns a boolean, or just pass a boolean
|
||||
* @param {Boolean | Function} options.noNext should the next button be hidden? You can pass a function that accepts the slug for the next button and returns a boolean, or just pass a boolean
|
||||
*/
|
||||
export const PrevNext = ({ slug, noPrev = false, noNext = false }) => {
|
||||
// Grab site navigation and slug lookup table from the useNavigatin hook
|
||||
const { siteNav, slugLut } = useNavigation()
|
||||
|
|
|
@ -2,6 +2,14 @@ import { components } from 'shared/components/mdx/index.mjs'
|
|||
import { Loading } from 'shared/components/spinner.mjs'
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
/**
|
||||
* Dynamically load and compile mdx
|
||||
* @param {Function} loader an import function to use to load the mdx
|
||||
* @param {String} site the site whose component set will be used in rendering the mdx
|
||||
* @return {Object} props
|
||||
* @return {React.component} props.MDX an component to render the loaded MDX
|
||||
* @return {Object} props.frontmatter the frontmatter loaded from the markdown
|
||||
*/
|
||||
export const useDynamicMdx = (loader, site = 'org') => {
|
||||
// State
|
||||
const [frontmatter, setFrontmatter] = useState({ title: `freeSewing.${site}` })
|
||||
|
|
|
@ -26,8 +26,6 @@ export const prebuildPosts = async (site) => {
|
|||
sorted[lang] = Object.keys(resultPages[lang]).sort(
|
||||
(a, b) => resultPages[lang][a].o - resultPages[lang][b].o
|
||||
)
|
||||
// get rid of the index page
|
||||
sorted[lang].shift()
|
||||
}
|
||||
|
||||
writeOps.push(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue