diff --git a/packages/freesewing.org/pages/blog/[slug].js b/packages/freesewing.org/pages/blog/[slug].js index 1613faf203f..f3901c63212 100644 --- a/packages/freesewing.org/pages/blog/[slug].js +++ b/packages/freesewing.org/pages/blog/[slug].js @@ -1,12 +1,14 @@ import Page from 'shared/components/wrappers/page.js' import useApp from 'site/hooks/useApp.js' -import strapiLoader from 'shared/strapi/loader' -import { posts } from 'site/prebuild/strapi.blog.en.js' import TimeAgo from 'react-timeago' import MdxWrapper from 'shared/components/wrappers/mdx' +import mdxCompiler from 'shared/mdx/compiler' import Markdown from 'react-markdown' import Head from 'next/head' -import HelpUs from 'site/components/help-us.js' +import { serverSideTranslations } from 'next-i18next/serverSideTranslations' +import { strapiHost } from 'shared/config/freesewing.mjs' +import { strapiImage } from 'shared/utils.js' +import { useTranslation } from 'next-i18next' const strapi = "https://posts.freesewing.org" @@ -18,7 +20,7 @@ const Author = ({ author }) => ( w-lg bg-cover bg-center rounded-full aspect-square hidden lg:block `} - style={{backgroundImage: `url(${strapi}${author?.img})`}} + style={{backgroundImage: `url(${strapiHost}${author?.image?.sizes?.small?.url})`}} > @@ -26,10 +28,10 @@ const Author = ({ author }) => (
{author?.displayname}
( Wrote this

- {author?.about} +
@@ -80,7 +82,7 @@ const PostPage = ({ post, author }) => {
{post.caption} @@ -95,23 +97,66 @@ const PostPage = ({ post, author }) => {
- +
{JSON.stringify(author, null ,2)}
) } -export const getStaticProps = async (props) => { - const { post, author } = await strapiLoader('en', 'dev', 'blog', props.params.slug) +/* + * getStaticProps() is used to fetch data at build-time. + * + * On this page, it is loading the blog content from strapi. + * + * This, in combination with getStaticPaths() below means this + * page will be used to render/generate all blog content. + * + * To learn more, see: https://nextjs.org/docs/basic-features/data-fetching + */ +export async function getStaticProps({ params, locale }) { - return { props: { post, author, slug: `blog/${props.params.slug}` } } + const { slug } = params + const post = await fetch( + `${strapiHost}/blogposts?_locale=${locale}&dev_ne=true&slug_eq=${slug}` + ) + .then(response => response.json()) + .then(data => data[0]) + .catch(err => console.log(err)) + + return { + props: { + post: { + slug, + ...(await mdxCompiler(post.body)), + title: post.title, + linktitle: post.linktitle, + date: post.date, + caption: post.caption, + image: { + w: post.image.width, + h: post.image.height, + url: post.image.url + }, + }, + author: { + displayname: post.author.displayname, + slug: post.author.slug, + about: post.author.about, + image: strapiImage(post.author.picture, ['small']), + ...(await mdxCompiler(post.author.about)), + }, + ...(await serverSideTranslations(locale)), + } + } } export const getStaticPaths = async () => { - const paths = [] - for (const post of posts) paths.push({ - params: {slug: post.slug} - }) + const paths = await fetch( + `${strapiHost}/blogposts?_locale=en&dev_ne=true` + ) + .then(response => response.json()) + .then(data => data.map(post => ({ params: { slug: post.slug } }))) + .catch(err => console.log(err)) return { paths, @@ -120,3 +165,4 @@ export const getStaticPaths = async () => { } export default PostPage + diff --git a/packages/freesewing.shared/components/mdx/index.js b/packages/freesewing.shared/components/mdx/index.js index 09592f384bf..bd226c12417 100644 --- a/packages/freesewing.shared/components/mdx/index.js +++ b/packages/freesewing.shared/components/mdx/index.js @@ -10,7 +10,7 @@ import rendertest from '@freesewing/rendertest' import tutorial from '@freesewing/tutorial' -const mdxCustomComponents = (app, t) => ({ +const mdxCustomComponents = (app=false) => ({ // Custom components Example: props => Object.values(order(current)) .filter(entry => (typeof entry === 'object')) const ReadMore = props => { + // Don't bother if we don't have the navigation tree in app + if (!props.app) return null const root = get(props.app.navigation, props.slug.split('/')) const list = [] diff --git a/packages/freesewing.shared/components/wrappers/mdx.js b/packages/freesewing.shared/components/wrappers/mdx.js index 27a4c5cb3f6..69abbd4718d 100644 --- a/packages/freesewing.shared/components/wrappers/mdx.js +++ b/packages/freesewing.shared/components/wrappers/mdx.js @@ -38,12 +38,13 @@ const MdxWrapper = ({mdx, app, t, components={}}) => { // React component for MDX content const MdxContent = mdxModule ? mdxModule.default : Fragment - return ( -
- {mdxModule && } - -
- ) + return app + ? ( +
+ {mdxModule && } + +
+ ) : } export default MdxWrapper diff --git a/packages/freesewing.shared/mdx/compiler.js b/packages/freesewing.shared/mdx/compiler.js new file mode 100644 index 00000000000..ad26c05bd51 --- /dev/null +++ b/packages/freesewing.shared/mdx/compiler.js @@ -0,0 +1,69 @@ +// MDX compiler +import { compile } from '@mdx-js/mdx' + +// Remark plugins we want to use +import remarkFrontmatter from 'remark-frontmatter' +import remarkGfm from 'remark-gfm' +import { remarkIntroPlugin } from './remark-intro-plugin.mjs' +import smartypants from 'remark-smartypants' +import mdxPluginToc from './mdx-plugin-toc.mjs' +// Rehype plugins we want to use +import rehypeHighlight from 'rehype-highlight' +import rehypeAutolinkHeadings from 'rehype-autolink-headings' +import rehypeSlug from 'rehype-slug' +// Simple frontmatter extractor +import frontmatter from 'front-matter' +/* + * Summary: Compiles the markdown it receives to MDX. + * + * @param (string) language - language to load (eg: 'en') + * @param (string) site - site to load (either 'dev' or 'org') + * @param (string) slug - slug of the page (eg: 'guides/patterns') + * + * @link https://mdxjs.com/guides/mdx-on-demand/ + * + */ +const mdxCompiler = async (md) => { + + const intro = [] + const mdx = String( + await compile(md, { + outputFormat: 'function-body', + remarkPlugins: [ + remarkFrontmatter, + remarkGfm, + smartypants, + [ + remarkIntroPlugin, + { intro } + ] + ], + rehypePlugins: [ + [rehypeHighlight, { plainText: ['dot', 'http'] }], + rehypeSlug, + rehypeAutolinkHeadings, + ], + }) + ) + + // This is not ideal as we're adding a second pass but for now it will do + // See: https://github.com/remarkjs/remark-toc/issues/37 + const toc = String( + await compile(md, { + outputFormat: 'function-body', + remarkPlugins: [ + remarkFrontmatter, + remarkGfm, + smartypants, + mdxPluginToc, + ], + rehypePlugins: [ + rehypeSlug, + ], + }) + ) + + return { mdx, intro, toc, frontmatter: frontmatter(md)?.attributes } +} + +export default mdxCompiler